|
|
|
@ -53,6 +53,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -53,6 +53,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ILTransformContext context; |
|
|
|
|
List<string> currentLowerCaseTypeOrMemberNames; |
|
|
|
|
Dictionary<string, int> reservedVariableNames; |
|
|
|
|
Dictionary<MethodDefinitionHandle, string> localFunctionMapping; |
|
|
|
|
HashSet<ILVariable> loopCounters; |
|
|
|
@ -63,6 +64,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -63,6 +64,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
this.context = context; |
|
|
|
|
|
|
|
|
|
reservedVariableNames = new Dictionary<string, int>(); |
|
|
|
|
currentLowerCaseTypeOrMemberNames = new List<string>(); |
|
|
|
|
var currentLowerCaseMemberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition); |
|
|
|
|
foreach (var name in currentLowerCaseMemberNames) |
|
|
|
|
currentLowerCaseTypeOrMemberNames.Add(name); |
|
|
|
|
var currentLowerCaseTypeNames = CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition); |
|
|
|
|
foreach (var name in currentLowerCaseTypeNames) |
|
|
|
|
{ |
|
|
|
|
currentLowerCaseTypeOrMemberNames.Add(name); |
|
|
|
|
AddExistingName(reservedVariableNames, name); |
|
|
|
|
} |
|
|
|
|
localFunctionMapping = new Dictionary<MethodDefinitionHandle, string>(); |
|
|
|
|
loopCounters = CollectLoopCounters(function); |
|
|
|
|
foreach (var f in function.Descendants.OfType<ILFunction>()) |
|
|
|
@ -146,6 +157,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -146,6 +157,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static IEnumerable<string> CollectAllLowerCaseMemberNames(ITypeDefinition type) |
|
|
|
|
{ |
|
|
|
|
foreach (var item in type.GetMembers(m => IsLowerCase(m.Name))) |
|
|
|
|
yield return item.Name; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static IEnumerable<string> CollectAllLowerCaseTypeNames(ITypeDefinition type) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
foreach (var item in type.ParentModule.TopLevelTypeDefinitions) |
|
|
|
|
{ |
|
|
|
|
if (item.Namespace != type.Namespace) |
|
|
|
|
continue; |
|
|
|
|
if (IsLowerCase(item.Name)) |
|
|
|
|
yield return item.Name; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool IsLowerCase(string name) |
|
|
|
|
{ |
|
|
|
|
return name.Length > 0 && char.ToLower(name[0]) == name[0]; |
|
|
|
@ -396,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -396,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
var proposedNameForAddress = variable.AddressInstructions.OfType<LdLoca>() |
|
|
|
|
.Select(arg => arg.Parent is CallInstruction c ? c.GetParameter(arg.ChildIndex)?.Name : null) |
|
|
|
|
.Where(arg => !string.IsNullOrWhiteSpace(arg)) |
|
|
|
|
.ToList(); |
|
|
|
|
.Except(currentLowerCaseTypeOrMemberNames).ToList(); |
|
|
|
|
if (proposedNameForAddress.Count > 0) |
|
|
|
|
{ |
|
|
|
|
proposedName = proposedNameForAddress[0]; |
|
|
|
@ -406,7 +435,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -406,7 +435,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
{ |
|
|
|
|
var proposedNameForStores = variable.StoreInstructions.OfType<StLoc>() |
|
|
|
|
.Select(expr => GetNameFromInstruction(expr.Value)) |
|
|
|
|
.ToList(); |
|
|
|
|
.Except(currentLowerCaseTypeOrMemberNames).ToList(); |
|
|
|
|
if (proposedNameForStores.Count == 1) |
|
|
|
|
{ |
|
|
|
|
proposedName = proposedNameForStores[0]; |
|
|
|
@ -416,7 +445,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -416,7 +445,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
{ |
|
|
|
|
var proposedNameForLoads = variable.LoadInstructions |
|
|
|
|
.Select(arg => GetNameForArgument(arg.Parent, arg.ChildIndex)) |
|
|
|
|
.ToList(); |
|
|
|
|
.Except(currentLowerCaseTypeOrMemberNames).ToList(); |
|
|
|
|
if (proposedNameForLoads.Count == 1) |
|
|
|
|
{ |
|
|
|
|
proposedName = proposedNameForLoads[0]; |
|
|
|
@ -426,7 +455,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -426,7 +455,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
{ |
|
|
|
|
var proposedNameForStoresFromNewObj = variable.StoreInstructions.OfType<StLoc>() |
|
|
|
|
.Select(expr => GetNameByType(GuessType(variable.Type, expr.Value, context))) |
|
|
|
|
.ToList(); |
|
|
|
|
.Except(currentLowerCaseTypeOrMemberNames).ToList(); |
|
|
|
|
if (proposedNameForStoresFromNewObj.Count == 1) |
|
|
|
|
{ |
|
|
|
|
proposedName = proposedNameForStoresFromNewObj[0]; |
|
|
|
@ -660,8 +689,35 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -660,8 +689,35 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
return variableType; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static Dictionary<string, int> CollectReservedVariableNames(ILFunction function, |
|
|
|
|
ILVariable existingVariable, bool mustResolveConflicts) |
|
|
|
|
{ |
|
|
|
|
var reservedVariableNames = new Dictionary<string, int>(); |
|
|
|
|
var rootFunction = function.Ancestors.OfType<ILFunction>().Single(f => f.Parent == null); |
|
|
|
|
foreach (var f in rootFunction.Descendants.OfType<ILFunction>()) |
|
|
|
|
{ |
|
|
|
|
foreach (var p in rootFunction.Parameters) |
|
|
|
|
{ |
|
|
|
|
AddExistingName(reservedVariableNames, p.Name); |
|
|
|
|
} |
|
|
|
|
foreach (var v in f.Variables.Where(v => v.Kind != VariableKind.Parameter)) |
|
|
|
|
{ |
|
|
|
|
if (v != existingVariable) |
|
|
|
|
AddExistingName(reservedVariableNames, v.Name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (mustResolveConflicts) |
|
|
|
|
{ |
|
|
|
|
var memberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition) |
|
|
|
|
.Concat(CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition)); |
|
|
|
|
foreach (var name in memberNames) |
|
|
|
|
AddExistingName(reservedVariableNames, name); |
|
|
|
|
} |
|
|
|
|
return reservedVariableNames; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, |
|
|
|
|
ILVariable existingVariable = null, string[] reservedNames = null) |
|
|
|
|
ILVariable existingVariable = null, bool mustResolveConflicts = false) |
|
|
|
|
{ |
|
|
|
|
if (function == null) |
|
|
|
|
throw new ArgumentNullException(nameof(function)); |
|
|
|
@ -669,12 +725,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -669,12 +725,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
{ |
|
|
|
|
return existingVariable.Name; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var reservedVariableNames = new Dictionary<string, int>(); |
|
|
|
|
foreach (var name in reservedNames ?? Array.Empty<string>()) |
|
|
|
|
{ |
|
|
|
|
reservedVariableNames[name] = 1; |
|
|
|
|
} |
|
|
|
|
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts); |
|
|
|
|
|
|
|
|
|
string baseName = GetNameFromInstruction(valueContext); |
|
|
|
|
if (string.IsNullOrEmpty(baseName)) |
|
|
|
@ -726,16 +777,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -726,16 +777,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
|
|
|
|
|
internal static string GenerateVariableName(ILFunction function, IType type, |
|
|
|
|
ILInstruction valueContext = null, ILVariable existingVariable = null, |
|
|
|
|
string[] reservedNames = null) |
|
|
|
|
bool mustResolveConflicts = false) |
|
|
|
|
{ |
|
|
|
|
if (function == null) |
|
|
|
|
throw new ArgumentNullException(nameof(function)); |
|
|
|
|
|
|
|
|
|
var reservedVariableNames = new Dictionary<string, int>(); |
|
|
|
|
foreach (var name in reservedNames ?? Array.Empty<string>()) |
|
|
|
|
{ |
|
|
|
|
reservedVariableNames[name] = 1; |
|
|
|
|
} |
|
|
|
|
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts); |
|
|
|
|
|
|
|
|
|
string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type); |
|
|
|
|
string proposedName = "obj"; |
|
|
|
|