Browse Source

Fix ConvertConstructorCallIntoInitializer transform.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
7e9f6bb9d6
  1. 10
      ICSharpCode.Decompiler/CSharp/Annotations.cs
  2. 75
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 4
      ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs
  4. 40
      ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs
  5. 15
      ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs
  6. 2
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs
  7. 2
      ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs
  8. 47
      ICSharpCode.Decompiler/CSharp/Transforms/TransformationPipeline.cs
  9. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  10. 4
      ICSharpCode.Decompiler/Tests/Helpers/Tester.cs
  11. 13
      ICSharpCode.Decompiler/Tests/TestRunner.cs

10
ICSharpCode.Decompiler/CSharp/Annotations.cs

@ -11,6 +11,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.Decompiler.CSharp namespace ICSharpCode.Decompiler.CSharp
@ -72,5 +73,14 @@ namespace ICSharpCode.Decompiler.CSharp
expression.Expression.AddAnnotation(resolveResult); expression.Expression.AddAnnotation(resolveResult);
return new ConvertedExpression(expression, resolveResult); return new ConvertedExpression(expression, resolveResult);
} }
/// <summary>
/// Retrieves the symbol associated with this AstNode, or null if no symbol is associated with the node.
/// </summary>
public static ISymbol GetSymbol(this AstNode node)
{
var rr = node.Annotation<ResolveResult>();
return rr != null ? rr.GetSymbol() : null;
}
} }
} }

75
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -16,20 +16,20 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.Decompiler.CSharp namespace ICSharpCode.Decompiler.CSharp
{ {
@ -40,7 +40,22 @@ namespace ICSharpCode.Decompiler.CSharp
NRefactoryCecilMapper cecilMapper; NRefactoryCecilMapper cecilMapper;
ICompilation compilation; ICompilation compilation;
TypeSystemAstBuilder typeSystemAstBuilder; TypeSystemAstBuilder typeSystemAstBuilder;
List<IAstTransform> astTransforms = new List<IAstTransform>(TransformationPipeline.CreatePipeline()); List<IAstTransform> astTransforms = new List<IAstTransform> {
//new PushNegation(),
//new DelegateConstruction(context),
//new PatternStatementTransform(context),
new ReplaceMethodCallsWithOperators(),
new IntroduceUnsafeModifier(),
new AddCheckedBlocks(),
//new DeclareVariables(context), // should run after most transforms that modify statements
new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables
//new DecimalConstantTransform(),
//new IntroduceUsingDeclarations(context),
//new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
//new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
//new CombineQueryExpressions(context),
//new FlattenSwitchBlocks(),
};
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
@ -84,6 +99,14 @@ namespace ICSharpCode.Decompiler.CSharp
return null; return null;
} }
void RunTransforms(AstNode rootNode)
{
var context = new TransformContext(compilation, cecilMapper);
foreach (var transform in astTransforms)
transform.Run(rootNode, context);
rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
}
public SyntaxTree DecompileWholeModuleAsSingleFile() public SyntaxTree DecompileWholeModuleAsSingleFile()
{ {
SyntaxTree syntaxTree = new SyntaxTree(); SyntaxTree syntaxTree = new SyntaxTree();
@ -100,10 +123,11 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var typeDef in g) { foreach (var typeDef in g) {
if (typeDef.Name == "<Module>" && typeDef.Members.Count == 0) if (typeDef.Name == "<Module>" && typeDef.Members.Count == 0)
continue; continue;
var typeDecl = Decompile(typeDef); var typeDecl = DoDecompile(typeDef);
groupNode.AddChild(typeDecl, SyntaxTree.MemberRole); groupNode.AddChild(typeDecl, SyntaxTree.MemberRole);
} }
} }
RunTransforms(syntaxTree);
return syntaxTree; return syntaxTree;
} }
@ -114,24 +138,23 @@ namespace ICSharpCode.Decompiler.CSharp
ITypeDefinition typeDef = cecilMapper.GetType(typeDefinition).GetDefinition(); ITypeDefinition typeDef = cecilMapper.GetType(typeDefinition).GetDefinition();
if (typeDef == null) if (typeDef == null)
throw new InvalidOperationException("Could not find type definition in NR type system"); throw new InvalidOperationException("Could not find type definition in NR type system");
return Decompile(typeDef); var decl = DoDecompile(typeDef);
RunTransforms(decl);
return decl;
} }
EntityDeclaration Decompile(ITypeDefinition typeDef) EntityDeclaration DoDecompile(ITypeDefinition typeDef)
{ {
var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef); var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef);
var typeDecl = entityDecl as TypeDeclaration; var typeDecl = entityDecl as TypeDeclaration;
if (typeDecl == null) if (typeDecl == null) {
{
// e.g. DelegateDeclaration // e.g. DelegateDeclaration
return entityDecl; return entityDecl;
} }
foreach (var method in typeDef.Methods) foreach (var method in typeDef.Methods) {
{
var methodDef = cecilMapper.GetCecil(method) as MethodDefinition; var methodDef = cecilMapper.GetCecil(method) as MethodDefinition;
if (methodDef != null) if (methodDef != null) {
{ var memberDecl = DoDecompile(methodDef, method);
var memberDecl = Decompile(methodDef, method);
typeDecl.Members.Add(memberDecl); typeDecl.Members.Add(memberDecl);
} }
} }
@ -145,10 +168,12 @@ namespace ICSharpCode.Decompiler.CSharp
var method = cecilMapper.GetMethod(methodDefinition); var method = cecilMapper.GetMethod(methodDefinition);
if (method == null) if (method == null)
throw new InvalidOperationException("Could not find method in NR type system"); throw new InvalidOperationException("Could not find method in NR type system");
return Decompile(methodDefinition, method); var decl = DoDecompile(methodDefinition, method);
RunTransforms(decl);
return decl;
} }
EntityDeclaration Decompile(MethodDefinition methodDefinition, IMethod method) EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method)
{ {
var entityDecl = typeSystemAstBuilder.ConvertEntity(method); var entityDecl = typeSystemAstBuilder.ConvertEntity(method);
if (methodDefinition.HasBody) { if (methodDefinition.HasBody) {
@ -159,9 +184,7 @@ namespace ICSharpCode.Decompiler.CSharp
function.CheckInvariant(); function.CheckInvariant();
var statementBuilder = new StatementBuilder(method, cecilMapper); var statementBuilder = new StatementBuilder(method, cecilMapper);
var body = statementBuilder.ConvertAsBlock(function.Body); var body = statementBuilder.ConvertAsBlock(function.Body);
foreach (var transform in astTransforms) {
transform.Run(body);
}
// insert variables at start of body // insert variables at start of body
Statement prevVarDecl = null; Statement prevVarDecl = null;
foreach (var v in function.Variables) { foreach (var v in function.Variables) {
@ -172,9 +195,7 @@ namespace ICSharpCode.Decompiler.CSharp
prevVarDecl = varDecl; prevVarDecl = varDecl;
} }
} }
body.AcceptVisitor(new InsertParenthesesVisitor {
InsertParenthesesForReadability = true
});
entityDecl.AddChild(body, Roles.Body); entityDecl.AddChild(body, Roles.Body);
} }
return entityDecl; return entityDecl;

4
ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs

@ -234,12 +234,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
#endregion #endregion
public void Run(AstNode node) public void Run(AstNode node, TransformContext context)
{ {
BlockStatement block = node as BlockStatement; BlockStatement block = node as BlockStatement;
if (block == null) { if (block == null) {
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
Run(child); Run(child, context);
} }
} else { } else {
Result r = GetResultFromBlock(block); Result r = GetResultFromBlock(block);

40
ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs

@ -21,6 +21,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms
@ -28,9 +30,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// <summary> /// <summary>
/// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer. /// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer.
/// </summary> /// </summary>
public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor<object, object>, IAstTransform public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor<TransformContext, object>, IAstTransform
{ {
public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, TransformContext context)
{ {
ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement; ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement;
if (stmt == null) if (stmt == null)
@ -71,19 +73,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
static readonly AstNode thisCallPattern = new ExpressionStatement(new ThisReferenceExpression().Invoke(".ctor", new Repeat(new AnyNode()))); static readonly AstNode thisCallPattern = new ExpressionStatement(new ThisReferenceExpression().Invoke(".ctor", new Repeat(new AnyNode())));
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, TransformContext context)
{ {
// Handle initializers on instance fields // Handle initializers on instance fields
HandleInstanceFieldInitializers(typeDeclaration.Members); HandleInstanceFieldInitializers(typeDeclaration.Members);
// Now convert base constructor calls to initializers: // Now convert base constructor calls to initializers:
base.VisitTypeDeclaration(typeDeclaration, data); base.VisitTypeDeclaration(typeDeclaration, context);
// Remove single empty constructor: // Remove single empty constructor:
RemoveSingleEmptyConstructor(typeDeclaration); RemoveSingleEmptyConstructor(typeDeclaration);
// Handle initializers on static fields: // Handle initializers on static fields:
HandleStaticFieldInitializers(typeDeclaration.Members); HandleStaticFieldInitializers(typeDeclaration.Members, context);
return null; return null;
} }
@ -92,8 +95,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var instanceCtors = members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); var instanceCtors = members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray(); var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray();
if (instanceCtorsNotChainingWithThis.Length > 0) { if (instanceCtorsNotChainingWithThis.Length > 0) {
MethodDefinition ctorMethodDef = instanceCtorsNotChainingWithThis[0].Annotation<MethodDefinition>(); var ctorMethodDef = instanceCtorsNotChainingWithThis[0].GetSymbol() as IMethod;
if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsValueType) if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsReferenceType == false)
return; return;
// Recognize field initializers: // Recognize field initializers:
@ -104,10 +107,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (!m.Success) if (!m.Success)
break; break;
FieldDefinition fieldDef = m.Get<AstNode>("fieldAccess").Single().Annotation<FieldReference>().ResolveWithinSameModule(); IField field = m.Get<AstNode>("fieldAccess").Single().GetSymbol() as IField;
if (fieldDef == null) if (field == null)
break; break;
AstNode fieldOrEventDecl = members.FirstOrDefault(f => f.Annotation<FieldDefinition>() == fieldDef); AstNode fieldOrEventDecl = members.FirstOrDefault(f => f.GetSymbol() == field);
if (fieldOrEventDecl == null) if (fieldOrEventDecl == null)
break; break;
Expression initializer = m.Get<Expression>("initializer").Single(); Expression initializer = m.Get<Expression>("initializer").Single();
@ -141,12 +144,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
void HandleStaticFieldInitializers(IEnumerable<AstNode> members) void HandleStaticFieldInitializers(IEnumerable<AstNode> members, TransformContext context)
{ {
// Convert static constructor into field initializers if the class is BeforeFieldInit // Convert static constructor into field initializers if the class is BeforeFieldInit
var staticCtor = members.OfType<ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); var staticCtor = members.OfType<ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static);
if (staticCtor != null) { if (staticCtor != null) {
MethodDefinition ctorMethodDef = staticCtor.Annotation<MethodDefinition>(); IMethod ctorMethod = staticCtor.GetSymbol() as IMethod;
MethodDefinition ctorMethodDef = context.CecilMapper.GetCecil(ctorMethod) as MethodDefinition;
if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) { if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) {
while (true) { while (true) {
ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement; ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement;
@ -155,10 +159,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
AssignmentExpression assignment = es.Expression as AssignmentExpression; AssignmentExpression assignment = es.Expression as AssignmentExpression;
if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign) if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign)
break; break;
FieldDefinition fieldDef = assignment.Left.Annotation<FieldReference>().ResolveWithinSameModule(); IField field = assignment.Left.GetSymbol() as IField;
if (fieldDef == null || !fieldDef.IsStatic) if (field == null || !field.IsStatic)
break; break;
FieldDeclaration fieldDecl = members.OfType<FieldDeclaration>().FirstOrDefault(f => f.Annotation<FieldDefinition>() == fieldDef); FieldDeclaration fieldDecl = members.OfType<FieldDeclaration>().FirstOrDefault(f => f.GetSymbol() == field);
if (fieldDecl == null) if (fieldDecl == null)
break; break;
fieldDecl.Variables.Single().Initializer = assignment.Right.Detach(); fieldDecl.Variables.Single().Initializer = assignment.Right.Detach();
@ -170,14 +174,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
void IAstTransform.Run(AstNode node) void IAstTransform.Run(AstNode node, TransformContext context)
{ {
// If we're viewing some set of members (fields are direct children of CompilationUnit), // If we're viewing some set of members (fields are direct children of CompilationUnit),
// we also need to handle those: // we also need to handle those:
HandleInstanceFieldInitializers(node.Children); HandleInstanceFieldInitializers(node.Children);
HandleStaticFieldInitializers(node.Children); HandleStaticFieldInitializers(node.Children, context);
node.AcceptVisitor(this, null); node.AcceptVisitor(this, context);
} }
} }
} }

15
ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs

@ -19,11 +19,24 @@
using System; using System;
using System.Threading; using System.Threading;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
public interface IAstTransform public interface IAstTransform
{ {
void Run(AstNode compilationUnit); void Run(AstNode rootNode, TransformContext context);
}
public class TransformContext
{
internal readonly NRefactoryCecilMapper CecilMapper;
public readonly ICompilation Compilation;
internal TransformContext(ICompilation compilation, NRefactoryCecilMapper cecilMapper)
{
this.Compilation = compilation;
this.CecilMapper = cecilMapper;
}
} }
} }

2
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
sealed class PointerArithmetic {} sealed class PointerArithmetic {}
public void Run(AstNode compilationUnit) public void Run(AstNode compilationUnit, TransformContext context)
{ {
compilationUnit.AcceptVisitor(this, null); compilationUnit.AcceptVisitor(this, null);
} }

2
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

@ -348,7 +348,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return null; return null;
} }
void IAstTransform.Run(AstNode node) void IAstTransform.Run(AstNode node, TransformContext context)
{ {
node.AcceptVisitor(this, null); node.AcceptVisitor(this, null);
} }

47
ICSharpCode.Decompiler/CSharp/Transforms/TransformationPipeline.cs

@ -1,47 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// 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.Threading;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.Decompiler.CSharp.Transforms
{
public static class TransformationPipeline
{
public static IAstTransform[] CreatePipeline()
{
return new IAstTransform[] {
//new PushNegation(),
//new DelegateConstruction(context),
//new PatternStatementTransform(context),
new ReplaceMethodCallsWithOperators(),
new IntroduceUnsafeModifier(),
new AddCheckedBlocks(),
//new DeclareVariables(context), // should run after most transforms that modify statements
new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables
//new DecimalConstantTransform(),
//new IntroduceUsingDeclarations(context),
//new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
//new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
//new CombineQueryExpressions(context),
//new FlattenSwitchBlocks(),
};
}
}
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -75,7 +75,6 @@
<Compile Include="CSharp\Transforms\IAstTransform.cs" /> <Compile Include="CSharp\Transforms\IAstTransform.cs" />
<Compile Include="CSharp\Transforms\IntroduceUnsafeModifier.cs" /> <Compile Include="CSharp\Transforms\IntroduceUnsafeModifier.cs" />
<Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" /> <Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="CSharp\Transforms\TransformationPipeline.cs" />
<Compile Include="IL\Instructions.cs"> <Compile Include="IL\Instructions.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>

4
ICSharpCode.Decompiler/Tests/Helpers/Tester.cs

@ -23,7 +23,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static class Tester public static class Tester
{ {
public static string CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug) public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug)
{ {
CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } }); CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters(); CompilerParameters options = new CompilerParameters();
@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
} }
throw new Exception(b.ToString()); throw new Exception(b.ToString());
} }
return results.PathToAssembly; return results;
} }
public static int Run(string assemblyFileName, out string output, out string error) public static int Run(string assemblyFileName, out string output, out string error)

13
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -1,4 +1,5 @@
using System; using System;
using System.CodeDom.Compiler;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -49,24 +50,24 @@ namespace ICSharpCode.Decompiler.Tests
void TestCompileDecompileCompileOutput(string testFileName, CompilerOptions options = CompilerOptions.UseDebug) void TestCompileDecompileCompileOutput(string testFileName, CompilerOptions options = CompilerOptions.UseDebug)
{ {
string outputFile = null, decompiledOutputFile = null; CompilerResults outputFile = null, decompiledOutputFile = null;
string output1, output2, error1, error2; string output1, output2, error1, error2;
try { try {
outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options); outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options);
string decompiledCodeFile = Tester.DecompileCSharp(outputFile); string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly);
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options); decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
int result1 = Tester.Run(outputFile, out output1, out error1); int result1 = Tester.Run(outputFile.PathToAssembly, out output1, out error1);
int result2 = Tester.Run(decompiledOutputFile, out output2, out error2); int result2 = Tester.Run(decompiledOutputFile.PathToAssembly, out output2, out error2);
Assert.AreEqual(result1, result2); Assert.AreEqual(result1, result2);
Assert.AreEqual(output1, output2); Assert.AreEqual(output1, output2);
Assert.AreEqual(error1, error2); Assert.AreEqual(error1, error2);
} finally { } finally {
if (outputFile != null) if (outputFile != null)
File.Delete(outputFile); outputFile.TempFiles.Delete();
if (decompiledOutputFile != null) if (decompiledOutputFile != null)
File.Delete(decompiledOutputFile); decompiledOutputFile.TempFiles.Delete();
} }
} }
} }

Loading…
Cancel
Save