Browse Source

Remove ILFunction.Read; Add AssignVariableNames

pull/832/head
Siegfried Pammer 8 years ago
parent
commit
66394b4e52
  1. 10
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 6
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 21
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  4. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 17
      ICSharpCode.Decompiler/IL/DetectedLoop.cs
  6. 13
      ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
  7. 348
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  8. 8
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  9. 5
      ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

10
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -115,6 +115,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
}, },
new DelegateConstruction(), new DelegateConstruction(),
new AssignVariableNames()
}; };
} }
@ -127,11 +128,11 @@ namespace ICSharpCode.Decompiler.CSharp
new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables
new DecimalConstantTransform(), new DecimalConstantTransform(),
new IntroduceUsingDeclarations(), new IntroduceUsingDeclarations(),
new FixNameCollisions(),
//new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations //new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
//new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods //new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
//new CombineQueryExpressions(context), //new CombineQueryExpressions(context),
//new FlattenSwitchBlocks(), //new FlattenSwitchBlocks(),
new FixNameCollisions(),
}; };
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
@ -612,8 +613,11 @@ namespace ICSharpCode.Decompiler.CSharp
void DecompileBody(MethodDefinition methodDefinition, IMethod method, EntityDeclaration entityDecl, ITypeResolveContext decompilationContext) void DecompileBody(MethodDefinition methodDefinition, IMethod method, EntityDeclaration entityDecl, ITypeResolveContext decompilationContext)
{ {
var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(decompilationContext); var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(decompilationContext);
ILFunction function = ILFunction.Read(specializingTypeSystem, methodDefinition, CancellationToken); var ilReader = new ILReader(specializingTypeSystem);
ilReader.UseDebugSymbols = settings.UseDebugSymbols;
var function = ilReader.ReadIL(methodDefinition.Body, CancellationToken);
function.CheckInvariant(ILPhase.Normal);
if (entityDecl != null) { if (entityDecl != null) {
int i = 0; int i = 0;
var parameters = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index); var parameters = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index);

6
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1415,8 +1415,8 @@ namespace ICSharpCode.Decompiler.CSharp
case BlockType.CollectionInitializer: case BlockType.CollectionInitializer:
case BlockType.ObjectInitializer: case BlockType.ObjectInitializer:
return TranslateObjectAndCollectionInitializer(block); return TranslateObjectAndCollectionInitializer(block);
case BlockType.CompoundOperator: case BlockType.PostfixOperator:
return TranslateCompoundOperator(block); return TranslatePostfixOperator(block);
default: default:
return ErrorExpression("Unknown block type: " + block.Type); return ErrorExpression("Unknown block type: " + block.Type);
} }
@ -1584,7 +1584,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ArrayCreateResolveResult(new ArrayType(compilation, type, dimensions), newArr.Indices.Select(i => Translate(i).ResolveResult).ToArray(), elementResolveResults)); .WithRR(new ArrayCreateResolveResult(new ArrayType(compilation, type, dimensions), newArr.Indices.Select(i => Translate(i).ResolveResult).ToArray(), elementResolveResults));
} }
TranslatedExpression TranslateCompoundOperator(Block block) TranslatedExpression TranslatePostfixOperator(Block block)
{ {
var targetInst = (block.Instructions.ElementAtOrDefault(0) as StLoc)?.Value; var targetInst = (block.Instructions.ElementAtOrDefault(0) as StLoc)?.Value;
var inst = (block.Instructions.ElementAtOrDefault(1) as StLoc)?.Value as BinaryNumericInstruction; var inst = (block.Instructions.ElementAtOrDefault(1) as StLoc)?.Value as BinaryNumericInstruction;

21
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -24,6 +24,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using System;
using System.Threading; using System.Threading;
namespace ICSharpCode.Decompiler.CSharp namespace ICSharpCode.Decompiler.CSharp
@ -307,10 +308,10 @@ namespace ICSharpCode.Decompiler.CSharp
continueStmt.Remove(); continueStmt.Remove();
return new DoWhileStatement { return new DoWhileStatement {
EmbeddedStatement = blockStatement, EmbeddedStatement = blockStatement,
Condition = exprBuilder.TranslateCondition(loop.Condition) Condition = exprBuilder.TranslateCondition(CombineConditions(loop.Conditions))
}; };
case LoopKind.For: case LoopKind.For:
conditionExpr = exprBuilder.TranslateCondition(loop.Condition); conditionExpr = exprBuilder.TranslateCondition(loop.Conditions[0]);
blockStatement = ConvertAsBlock(loop.Body); blockStatement = ConvertAsBlock(loop.Body);
var forBody = ConvertBlockContainer(blockStatement, container, loop.AdditionalBlocks, true); var forBody = ConvertBlockContainer(blockStatement, container, loop.AdditionalBlocks, true);
var forStmt = new ForStatement() { var forStmt = new ForStatement() {
@ -334,7 +335,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (!loop.Body.HasFlag(InstructionFlags.EndPointUnreachable)) if (!loop.Body.HasFlag(InstructionFlags.EndPointUnreachable))
blockStatement.Add(new BreakStatement()); blockStatement.Add(new BreakStatement());
} }
if (loop.Condition == null) { if (loop.Conditions == null) {
conditionExpr = new PrimitiveExpression(true); conditionExpr = new PrimitiveExpression(true);
Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount); Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount);
Debug.Assert(blockStatement.Statements.First() is LabelStatement); Debug.Assert(blockStatement.Statements.First() is LabelStatement);
@ -343,7 +344,7 @@ namespace ICSharpCode.Decompiler.CSharp
blockStatement.Statements.First().Remove(); blockStatement.Statements.First().Remove();
} }
} else { } else {
conditionExpr = exprBuilder.TranslateCondition(loop.Condition); conditionExpr = exprBuilder.TranslateCondition(loop.Conditions[0]);
blockStatement = ConvertBlockContainer(blockStatement, container, loop.AdditionalBlocks, true); blockStatement = ConvertBlockContainer(blockStatement, container, loop.AdditionalBlocks, true);
} }
if (blockStatement.LastOrDefault() is ContinueStatement stmt) if (blockStatement.LastOrDefault() is ContinueStatement stmt)
@ -352,6 +353,18 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
private ILInstruction CombineConditions(ILInstruction[] conditions)
{
ILInstruction condition = null;
foreach (var c in conditions) {
if (condition == null)
condition = new LogicNot(c);
else
condition = IfInstruction.LogicAnd(new LogicNot(c), condition);
}
return condition;
}
BlockStatement ConvertBlockContainer(BlockContainer container, bool isLoop) BlockStatement ConvertBlockContainer(BlockContainer container, bool isLoop)
{ {
return ConvertBlockContainer(new BlockStatement(), container, container.Blocks, isLoop); return ConvertBlockContainer(new BlockStatement(), container, container.Blocks, isLoop);

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -288,6 +288,7 @@
<Compile Include="IL\Patterns\AnyNode.cs" /> <Compile Include="IL\Patterns\AnyNode.cs" />
<Compile Include="IL\ControlFlow\YieldReturnDecompiler.cs" /> <Compile Include="IL\ControlFlow\YieldReturnDecompiler.cs" />
<Compile Include="IL\DetectedLoop.cs" /> <Compile Include="IL\DetectedLoop.cs" />
<Compile Include="IL\Transforms\AssignVariableNames.cs" />
<Compile Include="IL\Transforms\NullCoalescingTransform.cs" /> <Compile Include="IL\Transforms\NullCoalescingTransform.cs" />
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" /> <Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Util\UnicodeNewline.cs" /> <Compile Include="Util\UnicodeNewline.cs" />

17
ICSharpCode.Decompiler/IL/DetectedLoop.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
public BlockContainer Container { get; } public BlockContainer Container { get; }
public LoopKind Kind { get; private set; } public LoopKind Kind { get; private set; }
public ILInstruction Condition { get; private set; } public ILInstruction[] Conditions { get; private set; }
public Block IncrementBlock { get; private set; } public Block IncrementBlock { get; private set; }
public Block ContinueJumpTarget { get; private set; } // jumps to this block are "continue;" jumps public Block ContinueJumpTarget { get; private set; } // jumps to this block are "continue;" jumps
public ILInstruction Body { get; private set; } // null in case of DoWhile public ILInstruction Body { get; private set; } // null in case of DoWhile
@ -64,19 +64,15 @@ namespace ICSharpCode.Decompiler.IL
return new DetectedLoop(container).DetectLoopInternal(); return new DetectedLoop(container).DetectLoopInternal();
} }
private static Block FindDoWhileConditionBlock(BlockContainer container, out ILInstruction condition) private static Block FindDoWhileConditionBlock(BlockContainer container, List<ILInstruction> conditions)
{ {
condition = null;
foreach (var b in container.Blocks) { foreach (var b in container.Blocks) {
if (b.Instructions.Last().MatchBranch(container.EntryPoint)) { if (b.Instructions.Last().MatchBranch(container.EntryPoint)) {
// potentially the do-while-condition block // potentially the do-while-condition block
int i = b.Instructions.Count - 2; int i = b.Instructions.Count - 2;
while (i >= 0 && b.Instructions[i] is IfInstruction ifInst while (i >= 0 && b.Instructions[i] is IfInstruction ifInst
&& ifInst.TrueInst.MatchLeave(container) && ifInst.FalseInst.MatchNop()) { && ifInst.TrueInst.MatchLeave(container) && ifInst.FalseInst.MatchNop()) {
if (condition == null) conditions.Add(ifInst.Condition);
condition = new LogicNot(ifInst.Condition);
else
condition = IfInstruction.LogicAnd(new LogicNot(ifInst.Condition), condition);
i--; i--;
} }
if (i == -1) { if (i == -1) {
@ -105,7 +101,7 @@ namespace ICSharpCode.Decompiler.IL
if (IncrementBlock != null) if (IncrementBlock != null)
ContinueJumpTarget = IncrementBlock; ContinueJumpTarget = IncrementBlock;
} }
Condition = conditionInst; Conditions = new[] { conditionInst };
Body = trueInst; Body = trueInst;
if (IncrementBlock != null) { if (IncrementBlock != null) {
// for-loop // for-loop
@ -117,12 +113,13 @@ namespace ICSharpCode.Decompiler.IL
} else { } else {
// do-while or while(true)-loop // do-while or while(true)-loop
if (Container.EntryPoint.IncomingEdgeCount == 2) { if (Container.EntryPoint.IncomingEdgeCount == 2) {
Block conditionBlock = FindDoWhileConditionBlock(Container, out var conditionInst2); var conditions = new List<ILInstruction>();
Block conditionBlock = FindDoWhileConditionBlock(Container, conditions);
if (conditionBlock != null) { if (conditionBlock != null) {
Kind = LoopKind.DoWhile; Kind = LoopKind.DoWhile;
ContinueJumpTarget = conditionBlock; ContinueJumpTarget = conditionBlock;
Body = null; Body = null;
Condition = conditionInst2; Conditions = conditions.ToArray();
AdditionalBlocks = Container.Blocks.Where(b => b != conditionBlock).ToArray(); AdditionalBlocks = Container.Blocks.Where(b => b != conditionBlock).ToArray();
} }
} }

13
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

@ -151,18 +151,5 @@ namespace ICSharpCode.Decompiler.IL
Variables.Add(variable); Variables.Add(variable);
return variable; return variable;
} }
public static ILFunction Read(IDecompilerTypeSystem context, IMethod method, CancellationToken cancellationToken = default(CancellationToken))
{
return Read(context, (MethodDefinition)context.GetCecil(method), cancellationToken);
}
public static ILFunction Read(IDecompilerTypeSystem context, MethodDefinition methodDefinition, CancellationToken cancellationToken = default(CancellationToken))
{
var ilReader = new ILReader(context);
var function = ilReader.ReadIL(methodDefinition.Body, cancellationToken);
function.CheckInvariant(ILPhase.Normal);
return function;
}
} }
} }

348
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -0,0 +1,348 @@
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL.Transforms
{
public class AssignVariableNames : IILTransform
{
static readonly Dictionary<string, string> typeNameToVariableNameDict = new Dictionary<string, string> {
{ "System.Boolean", "flag" },
{ "System.Byte", "b" },
{ "System.SByte", "b" },
{ "System.Int16", "num" },
{ "System.Int32", "num" },
{ "System.Int64", "num" },
{ "System.UInt16", "num" },
{ "System.UInt32", "num" },
{ "System.UInt64", "num" },
{ "System.Single", "num" },
{ "System.Double", "num" },
{ "System.Decimal", "num" },
{ "System.String", "text" },
{ "System.Object", "obj" },
{ "System.Char", "c" }
};
ILTransformContext context;
string[] currentFieldNames;
Dictionary<ILVariable, string> mapping;
Dictionary<string, int> reservedVariableNames;
const char maxLoopVariableName = 'n';
public void Run(ILFunction function, ILTransformContext context)
{
this.context = context;
currentFieldNames = function.Method.DeclaringType.Fields.Select(f => f.Name).ToArray();
reservedVariableNames = new Dictionary<string, int>();
foreach (ILFunction f in function.Descendants.OfType<ILFunction>().Reverse()) {
PerformAssignment(f);
}
}
void PerformAssignment(ILFunction function)
{
foreach (var p in function.Method.Parameters)
AddExistingName(p.Name);
foreach (var v in function.Variables) {
switch (v.Kind) {
case VariableKind.Parameter:
case VariableKind.StackSlot: // keep generated names
AddExistingName(v.Name);
break;
default:
string varName = v.Name;
if (context.Settings.UseDebugSymbols) {
if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || !IsValidName(varName)) {
// don't use the name from the debug symbols if it looks like a generated name
v.Name = null;
} else {
// use the name from the debug symbols
// (but ensure we don't use the same name for two variables)
v.Name = GetAlternativeName(varName);
}
} else {
v.Name = null;
}
break;
}
}
// Now generate names:
var mapping = new Dictionary<ILVariable, string>(ILVariableEqualityComparer.Instance);
foreach (var inst in function.Descendants.OfType<IInstructionWithVariableOperand>()) {
var v = inst.Variable;
if (!mapping.TryGetValue(v, out string name)) {
if (string.IsNullOrEmpty(v.Name))
v.Name = GenerateNameForVariable(v, function.Body);
mapping.Add(v, v.Name);
} else {
v.Name = name;
}
}
}
static bool IsValidName(string varName)
{
if (string.IsNullOrEmpty(varName))
return false;
if (!(char.IsLetter(varName[0]) || varName[0] == '_'))
return false;
for (int i = 1; i < varName.Length; i++) {
if (!(char.IsLetterOrDigit(varName[i]) || varName[i] == '_'))
return false;
}
return true;
}
public string GetAlternativeName(string oldVariableName)
{
if (oldVariableName.Length == 1 && oldVariableName[0] >= 'i' && oldVariableName[0] <= maxLoopVariableName) {
for (char c = 'i'; c <= maxLoopVariableName; c++) {
if (!reservedVariableNames.ContainsKey(c.ToString())) {
reservedVariableNames.Add(c.ToString(), 1);
return c.ToString();
}
}
}
int number;
string nameWithoutDigits = SplitName(oldVariableName, out number);
if (!reservedVariableNames.ContainsKey(nameWithoutDigits)) {
reservedVariableNames.Add(nameWithoutDigits, number - 1);
}
int count = ++reservedVariableNames[nameWithoutDigits];
if (count != 1) {
return nameWithoutDigits + count.ToString();
} else {
return nameWithoutDigits;
}
}
string GenerateNameForVariable(ILVariable variable, ILInstruction methodBody)
{
string proposedName = null;
if (variable.Type.IsKnownType(KnownTypeCode.Int32)) {
// test whether the variable might be a loop counter
bool isLoopCounter = false;
foreach (BlockContainer possibleLoop in methodBody.Descendants.OfType<BlockContainer>().Reverse()) {
if (possibleLoop.EntryPoint.IncomingEdgeCount == 1) continue;
var loop = DetectedLoop.DetectLoop(possibleLoop);
if (loop.Kind != LoopKind.For) continue;
var condition = loop.Conditions?[0];
while (condition is LogicNot not)
condition = not.Argument;
if (condition is Comp comp) {
switch (comp.Kind) {
case ComparisonKind.GreaterThan:
case ComparisonKind.GreaterThanOrEqual:
case ComparisonKind.LessThan:
case ComparisonKind.LessThanOrEqual:
if (comp.Left.MatchLdLoc(variable)) {
isLoopCounter = true;
}
break;
}
}
}
if (isLoopCounter) {
// For loop variables, use i,j,k,l,m,n
for (char c = 'i'; c <= maxLoopVariableName; c++) {
if (!reservedVariableNames.ContainsKey(c.ToString())) {
proposedName = c.ToString();
break;
}
}
}
}
if (string.IsNullOrEmpty(proposedName)) {
var proposedNameForStores = variable.StoreInstructions.OfType<StLoc>()
.Select(expr => GetNameFromInstruction(expr.Value))
.Except(currentFieldNames).ToList();
if (proposedNameForStores.Count == 1) {
proposedName = proposedNameForStores[0];
}
}
if (string.IsNullOrEmpty(proposedName)) {
var proposedNameForLoads = variable.LoadInstructions
.Select(arg => GetNameForArgument(arg.Parent, arg.ChildIndex))
.Except(currentFieldNames).ToList();
if (proposedNameForLoads.Count == 1) {
proposedName = proposedNameForLoads[0];
}
}
if (string.IsNullOrEmpty(proposedName)) {
proposedName = GetNameByType(variable.Type);
}
// remove any numbers from the proposed name
int number;
proposedName = SplitName(proposedName, out number);
if (!reservedVariableNames.ContainsKey(proposedName)) {
reservedVariableNames.Add(proposedName, 0);
}
int count = ++reservedVariableNames[proposedName];
if (count > 1) {
return proposedName + count.ToString();
} else {
return proposedName;
}
}
static string GetNameFromInstruction(ILInstruction inst)
{
switch (inst) {
case LdObj ldobj:
IField field;
if (ldobj.Target is LdFlda ldflda)
field = ldflda.Field;
else if (ldobj.Target is LdsFlda ldsflda)
field = ldsflda.Field;
else
break;
return CleanUpVariableName(field.Name);
case CallInstruction call:
if (call is NewObj) break;
IMethod m = call.Method;
if (m.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && m.Parameters.Count == 0) {
// use name from properties, but not from indexers
return CleanUpVariableName(m.Name.Substring(4));
} else if (m.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) {
// use name from Get-methods
return CleanUpVariableName(m.Name.Substring(3));
}
break;
}
return null;
}
static string GetNameForArgument(ILInstruction parent, int i)
{
switch (parent) {
case StObj stobj:
IField field;
if (stobj.Target is LdFlda ldflda)
field = ldflda.Field;
else if (stobj.Target is LdsFlda ldsflda)
field = ldsflda.Field;
else
break;
return CleanUpVariableName(field.Name);
case CallInstruction call:
IMethod m = call.Method;
if (m.Parameters.Count == 1 && i == call.Arguments.Count - 1) {
// argument might be value of a setter
if (m.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) {
return CleanUpVariableName(m.Name.Substring(4));
} else if (m.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) {
return CleanUpVariableName(m.Name.Substring(3));
}
}
var p = m.Parameters.ElementAtOrDefault((!(call is NewObj) && !m.IsStatic) ? i - 1 : i);
if (p != null && !string.IsNullOrEmpty(p.Name))
return CleanUpVariableName(p.Name);
break;
case Return ret:
return "result";
}
return null;
}
string GetNameByType(IType type)
{
var git = type as ParameterizedType;
if (git != null && git.FullName == "System.Nullable`1" && git.TypeArguments.Count == 1) {
type = git.TypeArguments[0];
}
string name;
if (type is ArrayType) {
name = "array";
} else if (type is PointerType) {
name = "ptr";
} else if (type.IsAnonymousType()) {
name = "anon";
} else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) {
name = "ex";
} else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) {
name = type.Name;
// remove the 'I' for interfaces
if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2]))
name = name.Substring(1);
name = CleanUpVariableName(name);
}
return name;
}
void AddExistingName(string name)
{
if (string.IsNullOrEmpty(name))
return;
string nameWithoutDigits = SplitName(name, out int number);
if (reservedVariableNames.TryGetValue(nameWithoutDigits, out int existingNumber)) {
reservedVariableNames[nameWithoutDigits] = Math.Max(number, existingNumber);
} else {
reservedVariableNames.Add(nameWithoutDigits, number);
}
}
static string SplitName(string name, out int number)
{
// First, identify whether the name already ends with a number:
int pos = name.Length;
while (pos > 0 && name[pos - 1] >= '0' && name[pos - 1] <= '9')
pos--;
if (pos < name.Length) {
if (int.TryParse(name.Substring(pos), out number)) {
return name.Substring(0, pos);
}
}
number = 1;
return name;
}
static string CleanUpVariableName(string name)
{
// remove the backtick (generics)
int pos = name.IndexOf('`');
if (pos >= 0)
name = name.Substring(0, pos);
// remove field prefix:
if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal))
name = name.Substring(2);
else if (name.Length > 1 && name[0] == '_' && (char.IsLetter(name[1]) || name[1] == '_'))
name = name.Substring(1);
if (name.Length == 0)
return "obj";
else
return char.ToLower(name[0]) + name.Substring(1);
}
}
}

8
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -139,9 +139,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var targetMethod = ((IInstructionWithMethodOperand)value.Arguments[1]).Method; var targetMethod = ((IInstructionWithMethodOperand)value.Arguments[1]).Method;
if (IsAnonymousMethod(decompilationContext.CurrentTypeDefinition, targetMethod)) { if (IsAnonymousMethod(decompilationContext.CurrentTypeDefinition, targetMethod)) {
target = value.Arguments[0]; target = value.Arguments[0];
var methodDefinition = (Mono.Cecil.MethodDefinition)context.TypeSystem.GetCecil(targetMethod);
var localTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(targetMethod)); var localTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(targetMethod));
var function = ILFunction.Read(localTypeSystem, targetMethod, context.CancellationToken); var ilReader = new ILReader(localTypeSystem);
ilReader.UseDebugSymbols = context.Settings.UseDebugSymbols;
var function = ilReader.ReadIL(methodDefinition.Body, context.CancellationToken);
function.CheckInvariant(ILPhase.Normal);
var contextPrefix = targetMethod.Name; var contextPrefix = targetMethod.Name;
foreach (ILVariable v in function.Variables.Where(v => v.Kind != VariableKind.Parameter)) { foreach (ILVariable v in function.Variables.Where(v => v.Kind != VariableKind.Parameter)) {
v.Name = contextPrefix + v.Name; v.Name = contextPrefix + v.Name;

5
ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

@ -56,8 +56,9 @@ namespace ILSpy.BamlDecompiler
// decompile method and optimize the switch // decompile method and optimize the switch
var typeSystem = new DecompilerTypeSystem(method.Module); var typeSystem = new DecompilerTypeSystem(method.Module);
ILFunction function = ILFunction.Read(typeSystem, method); var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(method.Body);
var context = new ILTransformContext { Settings = new DecompilerSettings(), TypeSystem = typeSystem }; var context = new ILTransformContext { Settings = new DecompilerSettings(), TypeSystem = typeSystem };
function.RunTransforms(CSharpDecompiler.GetILTransforms(), context); function.RunTransforms(CSharpDecompiler.GetILTransforms(), context);

Loading…
Cancel
Save