Browse Source

Fix "Missing variable name in created C# code". Closes #81.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
2601a4901a
  1. 5
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 25
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  3. 2
      ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
  4. 26
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

5
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -599,7 +599,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -599,7 +599,7 @@ namespace ICSharpCode.Decompiler.Ast
astMethod.Modifiers = ConvertModifiers(methodDef);
else
astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context, astMethod.Parameters);
}
ConvertAttributes(astMethod, methodDef);
if (methodDef.HasCustomAttributes && astMethod.Parameters.Count > 0) {
@ -661,7 +661,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -661,7 +661,7 @@ namespace ICSharpCode.Decompiler.Ast
}
astMethod.Name = CleanName(methodDef.DeclaringType.Name);
astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context, astMethod.Parameters);
ConvertAttributes(astMethod, methodDef);
return astMethod;
}
@ -793,6 +793,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -793,6 +793,7 @@ namespace ICSharpCode.Decompiler.Ast
{
foreach(ParameterDefinition paramDef in paramCol) {
ParameterDeclaration astParam = new ParameterDeclaration();
astParam.AddAnnotation(paramDef);
astParam.Type = ConvertType(paramDef.ParameterType, paramDef);
astParam.Name = paramDef.Name;

25
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -24,7 +24,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -24,7 +24,15 @@ namespace ICSharpCode.Decompiler.Ast
HashSet<ILVariable> localVariablesToDefine = new HashSet<ILVariable>(); // local variables that are missing a definition
HashSet<ILVariable> implicitlyDefinedVariables = new HashSet<ILVariable>(); // local variables that are implicitly defined (e.g. catch handler)
public static BlockStatement CreateMethodBody(MethodDefinition methodDef, DecompilerContext context)
/// <summary>
/// Creates the body for the method definition.
/// </summary>
/// <param name="methodDef">Method definition to decompile.</param>
/// <param name="context">Decompilation context.</param>
/// <param name="parameters">Parameter declarations of the method being decompiled.
/// These are used to update the parameter names when the decompiler generates names for the parameters.</param>
/// <returns>Block for the method body</returns>
public static BlockStatement CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, IEnumerable<ParameterDeclaration> parameters = null)
{
MethodDefinition oldCurrentMethod = context.CurrentMethod;
Debug.Assert(oldCurrentMethod == null || oldCurrentMethod == methodDef);
@ -35,10 +43,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -35,10 +43,10 @@ namespace ICSharpCode.Decompiler.Ast
builder.context = context;
builder.typeSystem = methodDef.Module.TypeSystem;
if (Debugger.IsAttached) {
return builder.CreateMethodBody();
return builder.CreateMethodBody(parameters);
} else {
try {
return builder.CreateMethodBody();
return builder.CreateMethodBody(parameters);
} catch (OperationCanceledException) {
throw;
} catch (Exception ex) {
@ -50,7 +58,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -50,7 +58,7 @@ namespace ICSharpCode.Decompiler.Ast
}
}
public BlockStatement CreateMethodBody()
public BlockStatement CreateMethodBody(IEnumerable<ParameterDeclaration> parameters)
{
if (methodDef.Body == null) return null;
@ -69,6 +77,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -69,6 +77,15 @@ namespace ICSharpCode.Decompiler.Ast
Debug.Assert(context.CurrentMethod == methodDef);
NameVariables.AssignNamesToVariables(context, astBuilder.Parameters, allVariables, ilMethod);
if (parameters != null) {
foreach (var pair in (from p in parameters
join v in astBuilder.Parameters on p.Annotation<ParameterDefinition>() equals v.OriginalParameter
select new { p, v.Name }))
{
pair.p.Name = pair.Name;
}
}
context.CancellationToken.ThrowIfCancellationRequested();
Ast.BlockStatement astBlock = TransformBlock(ilMethod);
CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments

2
ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs

@ -17,7 +17,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -17,7 +17,7 @@ namespace ICSharpCode.Decompiler.Ast
public static T CopyAnnotationsFrom<T>(this T node, AstNode other) where T : AstNode
{
foreach (var annotation in other.Annotations<object>()) {
foreach (object annotation in other.Annotations) {
node.AddAnnotation(annotation);
}
return node;

26
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -114,24 +114,36 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -114,24 +114,36 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (!IsAnonymousMethod(context, method))
return false;
// Create AnonymousMethodExpression and prepare parameters
AnonymousMethodExpression ame = new AnonymousMethodExpression();
ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters));
ame.HasParameterList = true;
// Decompile the anonymous method:
DecompilerContext subContext = context.Clone();
subContext.CurrentMethod = method;
BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext);
BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext, ame.Parameters);
TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction, subContext);
body.AcceptVisitor(this, null);
AnonymousMethodExpression ame = new AnonymousMethodExpression();
bool isLambda = false;
if (method.Parameters.All(p => string.IsNullOrEmpty(p.Name))) {
ame.HasParameterList = false;
} else {
ame.HasParameterList = true;
ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters));
if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) {
isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
}
// Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
// and the parameters are not used in the method body
if (!isLambda && method.Parameters.All(p => string.IsNullOrEmpty(p.Name))) {
var parameterReferencingIdentifiers =
from ident in body.Descendants.OfType<IdentifierExpression>()
let v = ident.Annotation<ILVariable>()
where v != null && v.IsParameter && method.Parameters.Contains(v.OriginalParameter)
select ident;
if (!parameterReferencingIdentifiers.Any()) {
ame.Parameters.Clear();
ame.HasParameterList = false;
}
}
// Replace all occurrences of 'this' in the method body with the delegate's target:

Loading…
Cancel
Save