diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index 663b59236..eabbc2203 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -514,7 +514,7 @@ namespace Decompiler return MakeRef(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand)); } case Code.Ldc_I4: - return PrimitiveExpression((int)operand, byteCode.InferredType); + return MakePrimitive((int)operand, byteCode.InferredType); case Code.Ldc_I8: case Code.Ldc_R4: case Code.Ldc_R8: @@ -763,7 +763,7 @@ namespace Decompiler if (TypeAnalysis.IsBoolean(actualType)) return expr; if (actualIsIntegerOrEnum) { - return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, PrimitiveExpression(0, actualType)); + return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, MakePrimitive(0, actualType)); } else { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); } @@ -771,8 +771,8 @@ namespace Decompiler if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) { return new ConditionalExpression { Condition = expr, - TrueExpression = PrimitiveExpression(1, reqType), - FalseExpression = PrimitiveExpression(0, reqType) + TrueExpression = MakePrimitive(1, reqType), + FalseExpression = MakePrimitive(0, reqType) }; } if (actualIsIntegerOrEnum && requiredIsIntegerOrEnum) { @@ -782,7 +782,7 @@ namespace Decompiler } } - Expression PrimitiveExpression(long val, TypeReference type) + Expression MakePrimitive(long val, TypeReference type) { if (TypeAnalysis.IsBoolean(type) && val == 0) return new Ast.PrimitiveExpression(false); diff --git a/ICSharpCode.Decompiler/Ast/DeclareVariableInSmallestScope.cs b/ICSharpCode.Decompiler/Ast/DeclareVariableInSmallestScope.cs index ba60db563..af82e224d 100644 --- a/ICSharpCode.Decompiler/Ast/DeclareVariableInSmallestScope.cs +++ b/ICSharpCode.Decompiler/Ast/DeclareVariableInSmallestScope.cs @@ -34,6 +34,8 @@ namespace Decompiler Match m = assignmentPattern.Match(pos); if (m != null && m.Get("ident").Single().Identifier == name) { result = new VariableDeclarationStatement(type, name, m.Get("init").Single().Detach()); + result.Variables.Single().CopyAnnotationsFrom(((ExpressionStatement)pos).Expression); + result.CopyAnnotationsFrom(pos); pos.ReplaceWith(result); } else { result = new VariableDeclarationStatement(type, name); diff --git a/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs b/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs index dfc2e3486..8657037ad 100644 --- a/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs +++ b/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs @@ -15,6 +15,14 @@ namespace Decompiler return node; } + public static T CopyAnnotationsFrom(this T node, AstNode other) where T : AstNode + { + foreach (var annotation in other.Annotations()) { + node.AddAnnotation(annotation); + } + return node; + } + public static T Detach(this T node) where T : AstNode { node.Remove(); diff --git a/ICSharpCode.Decompiler/Ast/NameVariables.cs b/ICSharpCode.Decompiler/Ast/NameVariables.cs index 6e5805435..bea32a6a2 100644 --- a/ICSharpCode.Decompiler/Ast/NameVariables.cs +++ b/ICSharpCode.Decompiler/Ast/NameVariables.cs @@ -99,10 +99,10 @@ namespace Decompiler case ILCode.Ldfld: // Use the field name only if it's not a field on this (avoid confusion between local variables and fields) if (!(expr.Arguments[0].Code == ILCode.Ldarg && ((ParameterDefinition)expr.Arguments[0].Operand).Index < 0)) - return ((FieldReference)expr.Operand).Name; + return CleanUpVariableName(((FieldReference)expr.Operand).Name); break; case ILCode.Ldsfld: - return ((FieldReference)expr.Operand).Name; + return CleanUpVariableName(((FieldReference)expr.Operand).Name); case ILCode.Call: case ILCode.Callvirt: MethodReference mr = (MethodReference)expr.Operand; diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs index f33d51599..0a7cb2655 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.CSharp.PatternMatching; using Mono.Cecil; using Ast = ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp; @@ -142,7 +143,7 @@ namespace Decompiler.Transforms public override object VisitAssignmentExpression(AssignmentExpression assignment, object data) { base.VisitAssignmentExpression(assignment, data); - // First, combine "x = x op y" into "x op= y" + // Combine "x = x op y" into "x op= y" BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression; if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) { if (IsWithoutSideEffects(assignment.Left) && assignment.Left.Match(binary.Left) != null) { @@ -180,10 +181,27 @@ namespace Decompiler.Transforms } if (assignment.Operator != AssignmentOperatorType.Assign) { // If we found a shorter operator, get rid of the BinaryOperatorExpression: + assignment.CopyAnnotationsFrom(binary); assignment.Right = binary.Right; } } } + if (assignment.Operator == AssignmentOperatorType.Add || assignment.Operator == AssignmentOperatorType.Subtract) { + // detect increment/decrement + if (assignment.Right.Match(new PrimitiveExpression(1)) != null) { + // only if it's not a custom operator + if (assignment.Annotation() == null) { + UnaryOperatorType type; + // When the parent is an expression statement, pre- or post-increment doesn't matter; + // so we can pick post-increment which is more commonly used (for (int i = 0; i < x; i++)) + if (assignment.Parent is ExpressionStatement) + type = (assignment.Operator == AssignmentOperatorType.Add) ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement; + else + type = (assignment.Operator == AssignmentOperatorType.Add) ? UnaryOperatorType.Increment : UnaryOperatorType.Decrement; + assignment.ReplaceWith(new UnaryOperatorExpression(type, assignment.Left.Detach()).CopyAnnotationsFrom(assignment)); + } + } + } return null; } diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 38825bf99..ece707daf 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -36,7 +36,7 @@ namespace Decompiler.ControlFlow foreach(ILBlock block in method.GetSelfAndChildrenRecursive().ToList()) { ControlFlowGraph graph; graph = BuildGraph(block.Body, (ILLabel)block.EntryGoto.Operand); - graph.ComputeDominance(); + graph.ComputeDominance(context.CancellationToken); graph.ComputeDominanceFrontier(); block.Body = FindLoops(new HashSet(graph.Nodes.Skip(3)), graph.EntryPoint, false); } @@ -49,7 +49,7 @@ namespace Decompiler.ControlFlow // TODO: Fix if (graph == null) continue; - graph.ComputeDominance(); + graph.ComputeDominance(context.CancellationToken); graph.ComputeDominanceFrontier(); block.Body = FindConditions(new HashSet(graph.Nodes.Skip(3)), graph.EntryPoint); } diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 028d045c7..6c79b565e 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -646,6 +646,7 @@ namespace Decompiler case MetadataType.IntPtr: return true; case MetadataType.Byte: + case MetadataType.Char: case MetadataType.UInt16: case MetadataType.UInt32: case MetadataType.UInt64: diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index 4b064ee9b..32f382db4 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -11,7 +11,6 @@ MinHeight="200" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" - Icon="pack://application:,,,/ILSpy;component/images/ILSpy.ico" FocusManager.FocusedElement="{Binding ElementName=treeView}" > diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 7e2e418e6..66363a734 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -26,6 +26,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; +using System.Windows.Media.Imaging; using ICSharpCode.Decompiler; using ICSharpCode.ILSpy.TreeNodes; @@ -55,6 +56,11 @@ namespace ICSharpCode.ILSpy this.sessionSettings = new SessionSettings(spySettings); this.assemblyListManager = new AssemblyListManager(spySettings); + if (Environment.OSVersion.Version.Major >= 6) + this.Icon = new BitmapImage(new Uri("pack://application:,,,/ILSpy;component/images/ILSpy.ico")); + else + this.Icon = Images.AssemblyLoading; + this.DataContext = sessionSettings; this.Left = sessionSettings.WindowBounds.Left; this.Top = sessionSettings.WindowBounds.Top;