Browse Source

Add pattern for "for" loops. Closes #4.

pull/37/head
Daniel Grunwald 15 years ago
parent
commit
d5dcfea7e2
  1. 6
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 67
      ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

6
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -31,9 +31,14 @@ namespace Decompiler
MethodDefinition method = member as MethodDefinition; MethodDefinition method = member as MethodDefinition;
if (method != null && (method.IsGetter || method.IsSetter || method.IsAddOn || method.IsRemoveOn)) if (method != null && (method.IsGetter || method.IsSetter || method.IsAddOn || method.IsRemoveOn))
return true; return true;
if (method != null && method.Name.StartsWith("<", StringComparison.Ordinal) && method.IsCompilerGenerated())
return true;
TypeDefinition type = member as TypeDefinition; TypeDefinition type = member as TypeDefinition;
if (type != null && type.DeclaringType != null && type.Name.StartsWith("<>c__DisplayClass", StringComparison.Ordinal) && type.IsCompilerGenerated()) if (type != null && type.DeclaringType != null && type.Name.StartsWith("<>c__DisplayClass", StringComparison.Ordinal) && type.IsCompilerGenerated())
return true; return true;
FieldDefinition field = member as FieldDefinition;
if (field != null && field.Name.StartsWith("CS$<>", StringComparison.Ordinal) && field.IsCompilerGenerated())
return true;
return false; return false;
} }
@ -411,6 +416,7 @@ namespace Decompiler
{ {
// Add fields // Add fields
foreach(FieldDefinition fieldDef in typeDef.Fields) { foreach(FieldDefinition fieldDef in typeDef.Fields) {
if (MemberIsHidden(fieldDef)) continue;
astType.AddChild(CreateField(fieldDef), TypeDeclaration.MemberRole); astType.AddChild(CreateField(fieldDef), TypeDeclaration.MemberRole);
} }

67
ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

@ -19,26 +19,35 @@ namespace Decompiler.Transforms
{ {
TransformUsings(compilationUnit); TransformUsings(compilationUnit);
TransformForeach(compilationUnit); TransformForeach(compilationUnit);
TransformFor(compilationUnit);
} }
#region using /// <summary>
static readonly AstNode usingVarDeclPattern = new VariableDeclarationStatement { /// $type $variable = $initializer;
/// </summary>
static readonly AstNode variableDeclPattern = new VariableDeclarationStatement {
Type = new AnyNode("type").ToType(), Type = new AnyNode("type").ToType(),
Variables = { Variables = {
new NamedNode( new NamedNode(
"variable", "variable",
new VariableInitializer { new VariableInitializer {
Initializer = new AnyNode().ToExpression() Initializer = new AnyNode("initializer").ToExpression()
} }
).ToVariable() ).ToVariable()
} }
}; };
/// <summary>
/// Variable declaration without initializer.
/// </summary>
static readonly AstNode simpleVariableDefinition = new VariableDeclarationStatement { static readonly AstNode simpleVariableDefinition = new VariableDeclarationStatement {
Type = new AnyNode().ToType(), Type = new AnyNode().ToType(),
Variables = { Variables = {
new VariableInitializer() // any name but no initializer new VariableInitializer() // any name but no initializer
} }
}; };
#region using
static readonly AstNode usingTryCatchPattern = new TryCatchStatement { static readonly AstNode usingTryCatchPattern = new TryCatchStatement {
TryBlock = new AnyNode("body").ToBlock(), TryBlock = new AnyNode("body").ToBlock(),
FinallyBlock = new BlockStatement { FinallyBlock = new BlockStatement {
@ -65,7 +74,7 @@ namespace Decompiler.Transforms
public void TransformUsings(AstNode compilationUnit) public void TransformUsings(AstNode compilationUnit)
{ {
foreach (AstNode node in compilationUnit.Descendants.ToArray()) { foreach (AstNode node in compilationUnit.Descendants.ToArray()) {
Match m1 = usingVarDeclPattern.Match(node); Match m1 = variableDeclPattern.Match(node);
if (m1 == null) continue; if (m1 == null) continue;
AstNode tryCatch = node.NextSibling; AstNode tryCatch = node.NextSibling;
while (simpleVariableDefinition.Match(tryCatch) != null) while (simpleVariableDefinition.Match(tryCatch) != null)
@ -178,5 +187,55 @@ namespace Decompiler.Transforms
} }
} }
#endregion #endregion
#region for
WhileStatement forPattern = new WhileStatement {
Condition = new BinaryOperatorExpression {
Left = new NamedNode("ident", new IdentifierExpression()).ToExpression(),
Operator = BinaryOperatorType.Any,
Right = new AnyNode("endExpr").ToExpression()
},
EmbeddedStatement = new BlockStatement {
new Repeat(new AnyNode("statement")).ToStatement(),
new NamedNode(
"increment",
new ExpressionStatement(
new AssignmentExpression {
Left = new Backreference("ident").ToExpression(),
Operator = AssignmentOperatorType.Any,
Right = new AnyNode().ToExpression()
})).ToStatement(),
new ContinueStatement()
}
};
public void TransformFor(AstNode compilationUnit)
{
foreach (AstNode node in compilationUnit.Descendants.ToArray()) {
Match m1 = variableDeclPattern.Match(node);
if (m1 == null) continue;
AstNode next = node.NextSibling;
while (simpleVariableDefinition.Match(next) != null)
next = next.NextSibling;
Match m2 = forPattern.Match(next);
if (m2 == null) continue;
// ensure the variable in the for pattern is the same as in the declaration
if (m1.Get<VariableInitializer>("variable").Single().Name != m2.Get<IdentifierExpression>("ident").Single().Identifier)
continue;
WhileStatement loop = (WhileStatement)next;
node.Remove();
BlockStatement newBody = new BlockStatement();
foreach (Statement stmt in m2.Get<Statement>("statement"))
newBody.Add(stmt.Detach());
loop.ReplaceWith(
new ForStatement {
Initializers = { (VariableDeclarationStatement)node },
Condition = loop.Condition.Detach(),
Iterators = { m2.Get<Statement>("increment").Single().Detach() },
EmbeddedStatement = newBody
});
}
}
#endregion
} }
} }

Loading…
Cancel
Save