de4dot-cex/de4dot.code/renamer/TypeInfo.cs

910 lines
28 KiB
C#
Raw Normal View History

2011-11-18 23:55:54 +08:00
/*
2015-10-30 05:45:26 +08:00
Copyright (C) 2011-2015 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;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using de4dot.code.renamer.asmmodules;
2011-11-18 23:55:54 +08:00
using de4dot.blocks;
namespace de4dot.code.renamer {
public class TypeInfo : MemberInfo {
2011-11-18 23:55:54 +08:00
public string oldNamespace;
public string newNamespace;
2013-01-19 20:03:57 +08:00
public VariableNameState variableNameState = VariableNameState.Create();
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; }
}
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
}
2013-01-19 20:03:57 +08:00
bool IsWinFormsClass() {
return memberInfos.IsWinFormsClass(type);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public PropertyInfo Property(MPropertyDef prop) {
return memberInfos.Property(prop);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public EventInfo Event(MEventDef evt) {
return memberInfos.Event(evt);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public FieldInfo Field(MFieldDef field) {
return memberInfos.Field(field);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public MethodInfo Method(MMethodDef method) {
return memberInfos.Method(method);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public GenericParamInfo GenericParam(MGenericParamDef gparam) {
return memberInfos.GenericParam(gparam);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public ParamInfo Param(MParamDef param) {
return memberInfos.Param(param);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
TypeInfo GetBase() {
2011-11-18 23:55:54 +08:00
if (type.baseType == null)
return null;
TypeInfo baseInfo;
2013-01-19 20:03:57 +08:00
memberInfos.TryGetType(type.baseType.typeDef, out baseInfo);
2011-11-18 23:55:54 +08:00
return baseInfo;
}
2013-01-19 20:03:57 +08:00
bool IsModuleType() {
2012-11-04 07:50:24 +08:00
return type.TypeDef.IsGlobalModuleType;
2012-01-09 01:46:23 +08:00
}
2013-01-19 20:03:57 +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 != "") {
if (type.TypeDef.IsNested)
2011-12-26 06:03:53 +08:00
newNamespace = "";
2013-01-19 20:03:57 +08:00
else if (!checker.IsValidNamespaceName(oldNamespace))
newNamespace = state.CreateNamespace(this.type.TypeDef, oldNamespace);
2011-11-18 23:55:54 +08:00
}
string origClassName = null;
2013-01-19 20:03:57 +08:00
if (IsWinFormsClass())
origClassName = FindWindowsFormsClassName(type);
if (IsModuleType()) {
2012-01-09 01:46:23 +08:00
if (oldNamespace != "")
newNamespace = "";
2013-01-19 20:03:57 +08:00
Rename("<Module>");
2012-01-09 01:46:23 +08:00
}
2013-01-19 20:03:57 +08:00
else if (!checker.IsValidTypeName(oldName)) {
if (origClassName != null && checker.IsValidTypeName(origClassName))
Rename(state.GetTypeName(oldName, origClassName));
2011-11-18 23:55:54 +08:00
else {
2013-01-19 20:03:57 +08:00
ITypeNameCreator nameCreator = type.IsGlobalType() ?
2011-11-18 23:55:54 +08:00
state.globalTypeNameCreator :
state.internalTypeNameCreator;
string newBaseType = null;
2013-01-19 20:03:57 +08:00
TypeInfo baseInfo = GetBase();
2011-11-18 23:55:54 +08:00
if (baseInfo != null && baseInfo.renamed)
newBaseType = baseInfo.newName;
2013-01-19 20:03:57 +08:00
Rename(nameCreator.Create(type.TypeDef, newBaseType));
2011-11-18 23:55:54 +08:00
}
}
2013-01-19 20:03:57 +08:00
PrepareRenameGenericParams(type.GenericParams, checker);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public void MergeState() {
foreach (var ifaceInfo in type.interfaces)
2013-01-19 20:03:57 +08:00
MergeState(ifaceInfo.typeDef);
if (type.baseType != null)
2013-01-19 20:03:57 +08:00
MergeState(type.baseType.typeDef);
}
2013-01-19 20:03:57 +08:00
void MergeState(MTypeDef other) {
if (other == null)
return;
TypeInfo otherInfo;
2013-01-19 20:03:57 +08:00
if (!memberInfos.TryGetType(other, out otherInfo))
return;
2013-01-19 20:03:57 +08:00
variableNameState.Merge(otherInfo.variableNameState);
}
2013-01-19 20:03:57 +08:00
public void PrepareRenameMembers() {
MergeState();
2011-11-18 23:55:54 +08:00
2011-11-21 17:36:23 +08:00
foreach (var fieldDef in type.AllFields)
2013-01-19 20:03:57 +08:00
variableNameState.AddFieldName(Field(fieldDef).oldName);
2011-11-21 17:36:23 +08:00
foreach (var eventDef in type.AllEvents)
2013-01-19 20:03:57 +08:00
variableNameState.AddEventName(Event(eventDef).oldName);
2011-11-21 17:36:23 +08:00
foreach (var propDef in type.AllProperties)
2013-01-19 20:03:57 +08:00
variableNameState.AddPropertyName(Property(propDef).oldName);
2011-11-21 17:36:23 +08:00
foreach (var methodDef in type.AllMethods)
2013-01-19 20:03:57 +08:00
variableNameState.AddMethodName(Method(methodDef).oldName);
2011-11-21 17:36:23 +08:00
2013-01-19 20:03:57 +08:00
if (IsWinFormsClass())
InitializeWindowsFormsFieldsAndProps();
2011-11-18 23:55:54 +08:00
2013-01-19 20:03:57 +08:00
PrepareRenameFields();
}
2013-01-19 20:03:57 +08:00
public void PrepareRenamePropsAndEvents() {
MergeState();
PrepareRenameProperties();
PrepareRenameEvents();
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
void PrepareRenameFields() {
2011-11-21 17:36:23 +08:00
var checker = NameChecker;
2011-11-18 23:55:54 +08:00
if (type.TypeDef.IsEnum) {
2013-01-19 20:03:57 +08:00
var instanceFields = GetInstanceFields();
2011-11-21 17:36:23 +08:00
if (instanceFields.Count == 1)
2013-01-19 20:03:57 +08:00
Field(instanceFields[0]).Rename("value__");
2011-11-18 23:55:54 +08:00
int i = 0;
2013-01-19 20:03:57 +08:00
string nameFormat = HasFlagsAttribute() ? "flag_{0}" : "const_{0}";
2011-11-18 23:55:54 +08:00
foreach (var fieldDef in type.AllFieldsSorted) {
2013-01-19 20:03:57 +08:00
var fieldInfo = Field(fieldDef);
2011-11-21 17:36:23 +08:00
if (fieldInfo.renamed)
2011-11-18 23:55:54 +08:00
continue;
if (!fieldDef.FieldDef.IsStatic || !fieldDef.FieldDef.IsLiteral)
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +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) {
2013-01-19 20:03:57 +08:00
var fieldInfo = Field(fieldDef);
2011-11-21 17:36:23 +08:00
if (fieldInfo.renamed)
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +08:00
if (!checker.IsValidFieldName(fieldInfo.oldName))
fieldInfo.Rename(fieldInfo.suggestedName ?? variableNameState.GetNewFieldName(fieldDef.FieldDef));
2011-11-18 23:55:54 +08:00
}
}
2013-01-19 20:03:57 +08:00
List<MFieldDef> GetInstanceFields() {
var fields = new List<MFieldDef>();
2011-11-18 23:55:54 +08:00
foreach (var fieldDef in type.AllFields) {
if (!fieldDef.FieldDef.IsStatic)
2011-11-18 23:55:54 +08:00
fields.Add(fieldDef);
}
return fields;
}
2013-01-19 20:03:57 +08:00
bool HasFlagsAttribute() {
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;
}
2013-01-19 20:03:57 +08:00
void PrepareRenameProperties() {
2011-11-21 17:36:23 +08:00
foreach (var propDef in type.AllPropertiesSorted) {
2013-01-19 20:03:57 +08:00
if (propDef.IsVirtual())
2011-11-21 17:36:23 +08:00
continue;
2013-01-19 20:03:57 +08:00
PrepareRenameProperty(propDef);
2011-11-21 17:36:23 +08:00
}
}
2013-01-19 20:03:57 +08:00
void PrepareRenameProperty(MPropertyDef propDef) {
if (propDef.IsVirtual())
2011-11-21 17:36:23 +08:00
throw new ApplicationException("Can't rename virtual props here");
2013-01-19 20:03:57 +08:00
var propInfo = Property(propDef);
2011-11-21 17:36:23 +08:00
if (propInfo.renamed)
return;
string propName = propInfo.oldName;
2013-01-19 20:03:57 +08:00
if (!NameChecker.IsValidPropertyName(propName))
2011-11-21 17:36:23 +08:00
propName = propInfo.suggestedName;
2013-01-19 20:03:57 +08:00
if (!NameChecker.IsValidPropertyName(propName)) {
if (propDef.IsItemProperty())
propName = "Item";
else
2013-01-19 20:03:57 +08:00
propName = variableNameState.GetNewPropertyName(propDef.PropertyDef);
}
2013-01-19 20:03:57 +08:00
variableNameState.AddPropertyName(propName);
propInfo.Rename(propName);
2011-11-21 17:36:23 +08:00
2013-01-19 20:03:57 +08:00
RenameSpecialMethod(propDef.GetMethod, "get_" + propName);
RenameSpecialMethod(propDef.SetMethod, "set_" + propName);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
void PrepareRenameEvents() {
2011-11-21 17:36:23 +08:00
foreach (var eventDef in type.AllEventsSorted) {
2013-01-19 20:03:57 +08:00
if (eventDef.IsVirtual())
2011-11-21 17:36:23 +08:00
continue;
2013-01-19 20:03:57 +08:00
PrepareRenameEvent(eventDef);
2011-11-21 17:36:23 +08:00
}
}
2013-01-19 20:03:57 +08:00
void PrepareRenameEvent(MEventDef eventDef) {
if (eventDef.IsVirtual())
2011-11-21 17:36:23 +08:00
throw new ApplicationException("Can't rename virtual events here");
2013-01-19 20:03:57 +08:00
var eventInfo = Event(eventDef);
2011-11-21 17:36:23 +08:00
if (eventInfo.renamed)
return;
string eventName = eventInfo.oldName;
2013-01-19 20:03:57 +08:00
if (!NameChecker.IsValidEventName(eventName))
2011-11-21 17:36:23 +08:00
eventName = eventInfo.suggestedName;
2013-01-19 20:03:57 +08:00
if (!NameChecker.IsValidEventName(eventName))
eventName = variableNameState.GetNewEventName(eventDef.EventDef);
variableNameState.AddEventName(eventName);
eventInfo.Rename(eventName);
2011-11-21 17:36:23 +08:00
2013-01-19 20:03:57 +08:00
RenameSpecialMethod(eventDef.AddMethod, "add_" + eventName);
RenameSpecialMethod(eventDef.RemoveMethod, "remove_" + eventName);
RenameSpecialMethod(eventDef.RaiseMethod, "raise_" + eventName);
2011-11-21 17:36:23 +08:00
}
2013-01-19 20:03:57 +08:00
void RenameSpecialMethod(MMethodDef methodDef, string newName) {
2011-11-21 17:36:23 +08:00
if (methodDef == null)
return;
2013-01-19 20:03:57 +08:00
if (methodDef.IsVirtual())
2011-11-21 17:36:23 +08:00
return;
2013-01-19 20:03:57 +08:00
RenameMethod(methodDef, newName);
2011-11-18 23:55:54 +08:00
}
2013-01-19 20:03:57 +08:00
public void PrepareRenameMethods() {
MergeState();
2011-11-21 17:36:23 +08:00
foreach (var methodDef in type.AllMethodsSorted) {
2013-01-19 20:03:57 +08:00
if (methodDef.IsVirtual())
2011-11-21 17:36:23 +08:00
continue;
2013-01-19 20:03:57 +08:00
RenameMethod(methodDef);
2011-11-21 17:36:23 +08:00
}
}
2013-01-19 20:03:57 +08:00
public void PrepareRenameMethods2() {
2011-11-21 17:36:23 +08:00
var checker = NameChecker;
foreach (var methodDef in type.AllMethodsSorted) {
2013-01-19 20:03:57 +08:00
PrepareRenameMethodArgs(methodDef);
PrepareRenameGenericParams(methodDef.GenericParams, checker, methodDef.Owner == null ? null : methodDef.Owner.GenericParams);
2011-11-21 17:36:23 +08:00
}
}
2013-01-19 20:03:57 +08:00
void PrepareRenameMethodArgs(MMethodDef methodDef) {
2012-11-04 18:45:04 +08:00
VariableNameState newVariableNameState = null;
ParamInfo info;
if (methodDef.VisibleParameterCount > 0) {
2013-01-19 20:03:57 +08:00
if (IsEventHandler(methodDef)) {
info = Param(methodDef.ParamDefs[methodDef.VisibleParameterBaseIndex]);
if (!info.GotNewName())
info.newName = "sender";
2013-01-19 20:03:57 +08:00
info = Param(methodDef.ParamDefs[methodDef.VisibleParameterBaseIndex + 1]);
if (!info.GotNewName())
info.newName = "e";
2011-11-21 17:36:23 +08:00
}
else {
2013-01-19 20:03:57 +08:00
newVariableNameState = variableNameState.CloneParamsOnly();
2011-11-21 17:36:23 +08:00
var checker = NameChecker;
foreach (var paramDef in methodDef.ParamDefs) {
if (paramDef.IsHiddenThisParameter)
continue;
2013-01-19 20:03:57 +08:00
info = Param(paramDef);
if (info.GotNewName())
2011-11-21 17:36:23 +08:00
continue;
2013-01-19 20:03:57 +08:00
if (!checker.IsValidMethodArgName(info.oldName))
info.newName = newVariableNameState.GetNewParamName(info.oldName, paramDef.ParameterDef);
2011-11-21 17:36:23 +08:00
}
}
}
2013-01-19 20:03:57 +08:00
info = Param(methodDef.ReturnParamDef);
if (!info.GotNewName()) {
if (!NameChecker.IsValidMethodReturnArgName(info.oldName)) {
2012-11-04 18:45:04 +08:00
if (newVariableNameState == null)
2013-01-19 20:03:57 +08:00
newVariableNameState = variableNameState.CloneParamsOnly();
info.newName = newVariableNameState.GetNewParamName(info.oldName, methodDef.ReturnParamDef.ParameterDef);
2012-11-04 18:45:04 +08:00
}
}
if ((methodDef.Property != null && methodDef == methodDef.Property.SetMethod) ||
(methodDef.Event != null && (methodDef == methodDef.Event.AddMethod || methodDef == methodDef.Event.RemoveMethod))) {
if (methodDef.VisibleParameterCount > 0) {
2011-11-21 17:36:23 +08:00
var paramDef = methodDef.ParamDefs[methodDef.ParamDefs.Count - 1];
2013-01-19 20:03:57 +08:00
Param(paramDef).newName = "value";
2011-11-21 17:36:23 +08:00
}
}
}
2013-01-19 20:03:57 +08:00
bool CanRenameMethod(MMethodDef methodDef) {
var methodInfo = Method(methodDef);
if (methodDef.IsStatic()) {
2011-11-21 17:36:23 +08:00
if (methodInfo.oldName == ".cctor")
return false;
}
2013-01-19 20:03:57 +08:00
else if (methodDef.IsVirtual()) {
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;
}
2013-01-19 20:03:57 +08:00
public void RenameMethod(MMethodDef methodDef, string methodName) {
if (!CanRenameMethod(methodDef))
2011-11-21 17:36:23 +08:00
return;
2013-01-19 20:03:57 +08:00
var methodInfo = Method(methodDef);
variableNameState.AddMethodName(methodName);
methodInfo.Rename(methodName);
2011-11-21 17:36:23 +08:00
}
2013-01-19 20:03:57 +08:00
void RenameMethod(MMethodDef methodDef) {
if (methodDef.IsVirtual())
2011-11-21 17:36:23 +08:00
throw new ApplicationException("Can't rename virtual methods here");
2013-01-19 20:03:57 +08:00
if (!CanRenameMethod(methodDef))
2011-11-21 17:36:23 +08:00
return;
2013-01-19 20:03:57 +08:00
var info = Method(methodDef);
2011-11-21 17:36:23 +08:00
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.
2013-01-19 20:03:57 +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;
string newName2;
2013-01-19 20:03:57 +08:00
if (methodDef.MethodDef.ImplMap != null && !string.IsNullOrEmpty(newName2 = GetPinvokeName(methodDef)))
newName = newName2;
2013-01-19 20:03:57 +08:00
else if (methodDef.IsStatic())
2011-11-21 17:36:23 +08:00
nameCreator = variableNameState.staticMethodNameCreator;
else
nameCreator = variableNameState.instanceMethodNameCreator;
if (!string.IsNullOrEmpty(newName))
2011-11-21 17:36:23 +08:00
nameCreator = new NameCreator2(newName);
2013-01-19 20:03:57 +08:00
RenameMethod(methodDef, variableNameState.GetNewMethodName(info.oldName, nameCreator));
2011-11-21 17:36:23 +08:00
}
}
2013-01-19 20:03:57 +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+$"))
2013-01-19 20:03:57 +08:00
entryPoint = DotNetUtils.GetDllName(methodDef.MethodDef.ImplMap.Module.Name.String) + "_" + entryPoint.Substring(1);
2011-11-21 17:36:23 +08:00
return entryPoint;
}
2013-01-19 20:03:57 +08:00
static bool IsEventHandler(MMethodDef methodDef) {
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;
if (sig.Params[0].ElementType != ElementType.Object)
2012-11-04 07:50:24 +08:00
return false;
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
}
2013-01-19 20:03:57 +08:00
void PrepareRenameGenericParams(IEnumerable<MGenericParamDef> genericParams, INameChecker checker) {
PrepareRenameGenericParams(genericParams, checker, null);
2012-07-07 13:11:32 +08:00
}
2013-01-19 20:03:57 +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) {
2013-01-19 20:03:57 +08:00
var gpInfo = memberInfos.GenericParam(param);
2011-11-18 23:55:54 +08:00
usedNames[gpInfo.newName] = true;
}
}
foreach (var param in genericParams) {
2013-01-19 20:03:57 +08:00
var gpInfo = memberInfos.GenericParam(param);
if (!checker.IsValidGenericParamName(gpInfo.oldName) || usedNames.ContainsKey(gpInfo.oldName)) {
2011-11-18 23:55:54 +08:00
string newName;
do {
2013-01-19 20:03:57 +08:00
newName = nameCreator.Create();
2011-11-18 23:55:54 +08:00
} while (usedNames.ContainsKey(newName));
usedNames[newName] = true;
2013-01-19 20:03:57 +08:00
gpInfo.Rename(newName);
2011-11-18 23:55:54 +08:00
}
}
}
2013-01-19 20:03:57 +08:00
void InitializeWindowsFormsFieldsAndProps() {
2011-11-21 17:36:23 +08:00
var checker = NameChecker;
2011-11-18 23:55:54 +08:00
2012-11-22 16:14:51 +08:00
var ourFields = new FieldDefAndDeclaringTypeDict<MFieldDef>();
2011-11-18 23:55:54 +08:00
foreach (var fieldDef in type.AllFields)
2013-01-19 20:03:57 +08:00
ourFields.Add(fieldDef.FieldDef, fieldDef);
2012-11-22 16:14:51 +08:00
var ourMethods = new MethodDefAndDeclaringTypeDict<MMethodDef>();
2011-11-18 23:55:54 +08:00
foreach (var methodDef in type.AllMethods)
2013-01-19 20:03:57 +08:00
ourMethods.Add(methodDef.MethodDef, methodDef);
2011-11-18 23:55:54 +08:00
foreach (var methodDef in type.AllMethods) {
if (methodDef.MethodDef.Body == null)
2011-11-18 23:55:54 +08:00
continue;
if (methodDef.MethodDef.IsStatic || methodDef.MethodDef.IsVirtual)
2011-11-18 23:55:54 +08:00
continue;
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;
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
if (fieldName == null || !checker.IsValidFieldName(fieldName))
2011-11-18 23:55:54 +08:00
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;
2013-01-19 20:03:57 +08:00
var calledMethodDef = ourMethods.Find(calledMethod);
2011-12-17 02:33:44 +08:00
if (calledMethodDef == null)
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +08:00
fieldRef = GetFieldRef(calledMethodDef.MethodDef);
2011-11-18 23:55:54 +08:00
var propDef = calledMethodDef.Property;
if (propDef == null)
continue;
2013-01-19 20:03:57 +08:00
memberInfos.Property(propDef).suggestedName = fieldName;
2011-11-18 23:55:54 +08:00
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;
2013-01-19 20:03:57 +08:00
var fieldDef = ourFields.Find(fieldRef);
2011-12-17 02:33:44 +08:00
if (fieldDef == null)
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +08:00
var fieldInfo = memberInfos.Field(fieldDef);
2011-11-18 23:55:54 +08:00
if (fieldInfo.renamed)
continue;
2013-01-19 20:03:57 +08:00
fieldInfo.suggestedName = variableNameState.GetNewFieldName(fieldInfo.oldName, new NameCreator2(fieldName));
2011-11-18 23:55:54 +08:00
}
}
}
2013-01-19 20:03:57 +08:00
static IField GetFieldRef(MethodDef method) {
if (method == null || method.Body == null)
2011-11-18 23:55:54 +08:00
return null;
var instructions = method.Body.Instructions;
2011-11-18 23:55:54 +08:00
int index = 0;
2013-01-19 20:03:57 +08:00
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;
2013-01-19 20:03:57 +08:00
var ldfld = DotNetUtils.GetInstruction(instructions, ref index);
2011-11-18 23:55:54 +08:00
if (ldfld == null || ldfld.OpCode.Code != Code.Ldfld)
return null;
2013-01-19 20:03:57 +08:00
var ret = DotNetUtils.GetInstruction(instructions, ref index);
if (ret == null)
return null;
2012-11-04 07:50:24 +08:00
if (ret.IsStloc()) {
var local = ret.GetLocal(method.Body.Variables);
2013-01-19 20:03:57 +08:00
ret = DotNetUtils.GetInstruction(instructions, ref index);
2012-11-04 07:50:24 +08:00
if (ret == null || !ret.IsLdloc())
return null;
if (ret.GetLocal(method.Body.Variables) != local)
return null;
2013-01-19 20:03:57 +08:00
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
}
2013-01-19 20:03:57 +08:00
public void InitializeEventHandlerNames() {
2012-11-22 16:14:51 +08:00
var ourFields = new FieldDefAndDeclaringTypeDict<MFieldDef>();
2011-11-18 23:55:54 +08:00
foreach (var fieldDef in type.AllFields)
2013-01-19 20:03:57 +08:00
ourFields.Add(fieldDef.FieldDef, fieldDef);
2012-11-22 16:14:51 +08:00
var ourMethods = new MethodDefAndDeclaringTypeDict<MMethodDef>();
2011-11-18 23:55:54 +08:00
foreach (var methodDef in type.AllMethods)
2013-01-19 20:03:57 +08:00
ourMethods.Add(methodDef.MethodDef, methodDef);
2011-11-18 23:55:54 +08:00
2013-01-19 20:03:57 +08:00
InitVbEventHandlers(ourFields, ourMethods);
InitFieldEventHandlers(ourFields, ourMethods);
InitTypeEventHandlers(ourFields, ourMethods);
2011-11-18 23:55:54 +08:00
}
// 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.
2013-01-19 20:03:57 +08:00
void InitVbEventHandlers(FieldDefAndDeclaringTypeDict<MFieldDef> ourFields, MethodDefAndDeclaringTypeDict<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;
2013-01-19 20:03:57 +08:00
var handler = GetVbHandler(setterDef.MethodDef, out eventName);
2011-11-18 23:55:54 +08:00
if (handler == null)
continue;
2013-01-19 20:03:57 +08:00
var handlerDef = ourMethods.Find(handler);
2011-12-17 02:33:44 +08:00
if (handlerDef == null)
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +08:00
if (!checker.IsValidEventName(eventName))
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +08:00
memberInfos.Method(handlerDef).suggestedName = string.Format("{0}_{1}", memberInfos.Property(propDef).newName, eventName);
2011-11-18 23:55:54 +08:00
}
}
2013-01-19 20:03:57 +08:00
static IMethod GetVbHandler(MethodDef method, out string eventName) {
2011-11-18 23:55:54 +08:00
eventName = null;
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;
if (sig.Params.Count != 1)
2011-11-18 23:55:54 +08:00
return null;
if (method.Body.Variables.Count != 1)
2011-11-18 23:55:54 +08:00
return null;
2013-01-19 20:03:57 +08:00
if (!IsEventHandlerType(method.Body.Variables[0].Type))
2011-11-18 23:55:54 +08:00
return null;
var instructions = method.Body.Instructions;
2011-11-18 23:55:54 +08:00
int index = 0;
2013-01-19 20:03:57 +08:00
int newobjIndex = FindInstruction(instructions, index, Code.Newobj);
if (newobjIndex == -1 || FindInstruction(instructions, newobjIndex + 1, Code.Newobj) != -1)
2011-11-18 23:55:54 +08:00
return null;
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
if (!FindEventCall(instructions, ref index, out removeField, out removeMethod))
2011-11-18 23:55:54 +08:00
return null;
2013-01-19 20:03:57 +08:00
if (!FindEventCall(instructions, ref index, out addField, out addMethod))
2011-11-18 23:55:54 +08:00
return null;
2013-01-19 20:03:57 +08:00
if (FindInstruction(instructions, index, Code.Callvirt) != -1)
2011-11-18 23:55:54 +08:00
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;
}
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
int callvirt = FindInstruction(instructions, index, Code.Callvirt);
2011-11-18 23:55:54 +08:00
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;
}
2013-01-19 20:03:57 +08:00
static int FindInstruction(IList<Instruction> instructions, int index, Code code) {
2011-11-18 23:55:54 +08:00
for (int i = index; i < instructions.Count; i++) {
if (instructions[i].OpCode.Code == code)
return i;
}
return -1;
}
2013-01-19 20:03:57 +08:00
void InitFieldEventHandlers(FieldDefAndDeclaringTypeDict<MFieldDef> ourFields, MethodDefAndDeclaringTypeDict<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) {
if (methodDef.MethodDef.Body == null)
2011-11-18 23:55:54 +08:00
continue;
if (methodDef.MethodDef.IsStatic)
2011-11-18 23:55:54 +08:00
continue;
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;
2013-01-19 20:03:57 +08:00
var fieldDef = ourFields.Find(fieldRef);
2011-12-17 02:33:44 +08:00
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) {
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
var handlerMethod = ourMethods.Find(methodRef);
2011-12-17 02:33:44 +08:00
if (handlerMethod == null)
2011-11-18 23:55:54 +08:00
continue;
var newobj = instructions[index++];
if (newobj.OpCode.Code != Code.Newobj)
continue;
2013-01-19 20:03:57 +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);
2013-01-19 20:03:57 +08:00
if (!checker.IsValidEventName(eventName))
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +08:00
memberInfos.Method(handlerMethod).suggestedName = string.Format("{0}_{1}", memberInfos.Field(fieldDef).newName, eventName);
2011-11-18 23:55:54 +08:00
}
}
}
2013-01-19 20:03:57 +08:00
void InitTypeEventHandlers(FieldDefAndDeclaringTypeDict<MFieldDef> ourFields, MethodDefAndDeclaringTypeDict<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) {
if (methodDef.MethodDef.Body == null)
2011-11-18 23:55:54 +08:00
continue;
if (methodDef.MethodDef.IsStatic)
2011-11-18 23:55:54 +08:00
continue;
var method = methodDef.MethodDef;
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;
2013-01-19 20:03:57 +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 {
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
var handlerDef = ourMethods.Find(handler);
2011-12-17 02:33:44 +08:00
if (handlerDef == null)
2011-11-18 23:55:54 +08:00
continue;
var newobj = instructions[index++];
if (newobj.OpCode.Code != Code.Newobj)
continue;
2013-01-19 20:03:57 +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);
2013-01-19 20:03:57 +08:00
if (!checker.IsValidEventName(eventName))
2011-11-18 23:55:54 +08:00
continue;
2013-01-19 20:03:57 +08:00
memberInfos.Method(handlerDef).suggestedName = string.Format("{0}_{1}", newName, eventName);
2011-11-18 23:55:54 +08:00
}
}
}
2013-01-19 20:03:57 +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
}
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
if (!DotNetUtils.IsMethod(method, "System.Void", "(System.Object,System.IntPtr)"))
2011-11-18 23:55:54 +08:00
return false;
2013-01-19 20:03:57 +08:00
if (!IsEventHandlerType(method.DeclaringType))
2011-11-18 23:55:54 +08:00
return false;
return true;
}
2013-01-19 20:03:57 +08:00
static bool IsEventHandlerType(IType type) {
2011-11-18 23:55:54 +08:00
return type.FullName.EndsWith("EventHandler", StringComparison.Ordinal);
}
2013-01-19 20:03:57 +08:00
string FindWindowsFormsClassName(MTypeDef type) {
2011-11-18 23:55:54 +08:00
foreach (var methodDef in type.AllMethods) {
if (methodDef.MethodDef.Body == null)
2011-11-18 23:55:54 +08:00
continue;
if (methodDef.MethodDef.IsStatic || methodDef.MethodDef.IsVirtual)
2011-11-18 23:55:54 +08:00
continue;
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;
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
FindInitializeComponentMethod(type, methodDef);
2011-11-18 23:55:54 +08:00
return className;
}
}
return null;
}
2013-01-19 20:03:57 +08:00
void FindInitializeComponentMethod(MTypeDef type, MMethodDef possibleInitMethod) {
2011-11-18 23:55:54 +08:00
foreach (var methodDef in type.AllMethods) {
if (methodDef.MethodDef.Name != ".ctor")
2011-11-18 23:55:54 +08:00
continue;
if (methodDef.MethodDef.Body == null)
2011-11-18 23:55:54 +08:00
continue;
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;
2013-01-19 20:03:57 +08:00
memberInfos.Method(possibleInitMethod).suggestedName = "InitializeComponent";
2011-11-18 23:55:54 +08:00
return;
}
}
}
2013-01-19 20:03:57 +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;
}
}
}