|
|
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
@@ -21,6 +21,7 @@ using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Threading; |
|
|
|
|
using ICSharpCode.Decompiler.ILAst; |
|
|
|
|
using ICSharpCode.NRefactory.CSharp; |
|
|
|
|
using ICSharpCode.NRefactory.CSharp.Analysis; |
|
|
|
|
|
|
|
|
@ -35,6 +36,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
@@ -35,6 +36,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
|
|
|
|
|
{ |
|
|
|
|
public AstType Type; |
|
|
|
|
public string Name; |
|
|
|
|
public ILVariable Variable; |
|
|
|
|
|
|
|
|
|
public AssignmentExpression ReplacedAssignment; |
|
|
|
|
public Statement InsertionPoint; |
|
|
|
@ -57,9 +59,12 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
@@ -57,9 +59,12 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
|
|
|
|
|
foreach (var v in variablesToDeclare) { |
|
|
|
|
if (v.ReplacedAssignment == null) { |
|
|
|
|
BlockStatement block = (BlockStatement)v.InsertionPoint.Parent; |
|
|
|
|
var vds = new VariableDeclarationStatement((AstType)v.Type.Clone(), v.Name); |
|
|
|
|
if(v.Variable != null) |
|
|
|
|
vds.Variables.First().AddAnnotation(v.Variable); |
|
|
|
|
block.Statements.InsertBefore( |
|
|
|
|
v.InsertionPoint, |
|
|
|
|
new VariableDeclarationStatement((AstType)v.Type.Clone(), v.Name)); |
|
|
|
|
vds); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// First do all the insertions, then do all the replacements. This is necessary because a replacement might remove our reference point from the AST.
|
|
|
|
@ -67,9 +72,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
@@ -67,9 +72,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
|
|
|
|
|
if (v.ReplacedAssignment != null) { |
|
|
|
|
// We clone the right expression so that it doesn't get removed from the old ExpressionStatement,
|
|
|
|
|
// which might be still in use by the definite assignment graph.
|
|
|
|
|
var variableInit = new VariableInitializer(v.Name, v.ReplacedAssignment.Right.Detach()) |
|
|
|
|
.CopyAnnotationsFrom(v.ReplacedAssignment) |
|
|
|
|
.CopyAnnotationsFrom(v.ReplacedAssignment.Left) |
|
|
|
|
.WithAnnotation(v.Variable); |
|
|
|
|
VariableDeclarationStatement varDecl = new VariableDeclarationStatement { |
|
|
|
|
Type = (AstType)v.Type.Clone(), |
|
|
|
|
Variables = { new VariableInitializer(v.Name, v.ReplacedAssignment.Right.Detach()).CopyAnnotationsFrom(v.ReplacedAssignment) } |
|
|
|
|
Variables = { variableInit } |
|
|
|
|
}; |
|
|
|
|
ExpressionStatement es = v.ReplacedAssignment.Parent as ExpressionStatement; |
|
|
|
|
if (es != null) { |
|
|
|
@ -102,7 +111,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
@@ -102,7 +111,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
|
|
|
|
|
foreach (VariableDeclarationStatement varDecl in variables) { |
|
|
|
|
string variableName = varDecl.Variables.Single().Name; |
|
|
|
|
bool allowPassIntoLoops = varDecl.Variables.Single().Annotation<DelegateConstruction.CapturedVariableAnnotation>() == null; |
|
|
|
|
DeclareVariableInBlock(daa, block, varDecl.Type, variableName, allowPassIntoLoops); |
|
|
|
|
ILVariable ilVariable = varDecl.Variables.Single().Annotation<ILVariable>(); |
|
|
|
|
DeclareVariableInBlock(daa, block, varDecl.Type, variableName, allowPassIntoLoops, ilVariable); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -111,7 +121,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
@@ -111,7 +121,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void DeclareVariableInBlock(DefiniteAssignmentAnalysis daa, BlockStatement block, AstType type, string variableName, bool allowPassIntoLoops) |
|
|
|
|
void DeclareVariableInBlock(DefiniteAssignmentAnalysis daa, BlockStatement block, AstType type, string variableName, bool allowPassIntoLoops, ILVariable ilVariable) |
|
|
|
|
{ |
|
|
|
|
// declarationPoint: The point where the variable would be declared, if we decide to declare it in this block
|
|
|
|
|
Statement declarationPoint = null; |
|
|
|
@ -127,52 +137,52 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
@@ -127,52 +137,52 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
|
|
|
|
|
ForStatement forStmt = stmt as ForStatement; |
|
|
|
|
if (forStmt != null && forStmt.Initializers.Count == 1) { |
|
|
|
|
// handle the special case of moving a variable into the for initializer
|
|
|
|
|
if (TryConvertAssignmentExpressionIntoVariableDeclaration(forStmt.Initializers.Single(), type, variableName)) |
|
|
|
|
if (TryConvertAssignmentExpressionIntoVariableDeclaration(forStmt.Initializers.Single(), type, variableName, ilVariable)) |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
UsingStatement usingStmt = stmt as UsingStatement; |
|
|
|
|
if (usingStmt != null && usingStmt.ResourceAcquisition is AssignmentExpression) { |
|
|
|
|
// handle the special case of moving a variable into a using statement
|
|
|
|
|
if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName)) |
|
|
|
|
if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName, ilVariable)) |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
foreach (AstNode child in stmt.Children) { |
|
|
|
|
BlockStatement subBlock = child as BlockStatement; |
|
|
|
|
if (subBlock != null) { |
|
|
|
|
DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops); |
|
|
|
|
DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops, ilVariable); |
|
|
|
|
} else if (HasNestedBlocks(child)) { |
|
|
|
|
foreach (BlockStatement nestedSubBlock in child.Children.OfType<BlockStatement>()) { |
|
|
|
|
DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, allowPassIntoLoops); |
|
|
|
|
DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, allowPassIntoLoops, ilVariable); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Try converting an assignment expression into a VariableDeclarationStatement
|
|
|
|
|
if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) { |
|
|
|
|
if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName, ilVariable)) { |
|
|
|
|
// Declare the variable in front of declarationPoint
|
|
|
|
|
variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, InsertionPoint = declarationPoint }); |
|
|
|
|
variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, InsertionPoint = declarationPoint, Variable = ilVariable }); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool TryConvertAssignmentExpressionIntoVariableDeclaration(Statement declarationPoint, AstType type, string variableName) |
|
|
|
|
bool TryConvertAssignmentExpressionIntoVariableDeclaration(Statement declarationPoint, AstType type, string variableName, ILVariable ilVariable) |
|
|
|
|
{ |
|
|
|
|
// convert the declarationPoint into a VariableDeclarationStatement
|
|
|
|
|
ExpressionStatement es = declarationPoint as ExpressionStatement; |
|
|
|
|
if (es != null) { |
|
|
|
|
return TryConvertAssignmentExpressionIntoVariableDeclaration(es.Expression, type, variableName); |
|
|
|
|
return TryConvertAssignmentExpressionIntoVariableDeclaration(es.Expression, type, variableName, ilVariable); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool TryConvertAssignmentExpressionIntoVariableDeclaration(Expression expression, AstType type, string variableName) |
|
|
|
|
bool TryConvertAssignmentExpressionIntoVariableDeclaration(Expression expression, AstType type, string variableName, ILVariable ilVariable) |
|
|
|
|
{ |
|
|
|
|
AssignmentExpression ae = expression as AssignmentExpression; |
|
|
|
|
if (ae != null && ae.Operator == AssignmentOperatorType.Assign) { |
|
|
|
|
IdentifierExpression ident = ae.Left as IdentifierExpression; |
|
|
|
|
if (ident != null && ident.Identifier == variableName) { |
|
|
|
|
variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, ReplacedAssignment = ae }); |
|
|
|
|
variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, ReplacedAssignment = ae, Variable = ilVariable }); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|