From 30fe30c2361880314d00c68906feeb90981efe01 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 14:19:09 +0200 Subject: [PATCH] Fix DecimalConstantTransform. --- .../Transforms/DecimalConstantTransform.cs | 137 +++--------------- .../Ast/Transforms/TransformationPipeline.cs | 2 +- 2 files changed, 18 insertions(+), 121 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs index 66df123d2..298682afb 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs @@ -17,145 +17,42 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.Generic; -using System.Linq; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.PatternMatching; +using Mono.Cecil; namespace ICSharpCode.Decompiler.Ast.Transforms { /// - /// Description of DecimalConstantTransform. + /// Transforms decimal constant fields. /// public class DecimalConstantTransform : DepthFirstAstVisitor, IAstTransform { - static readonly ICSharpCode.NRefactory.CSharp.Attribute decimalConstantAttribute = new ICSharpCode.NRefactory.CSharp.Attribute { - Type = new SimpleType("DecimalConstant"), - Arguments = { new Repeat(new AnyNode()) } - }; - - static readonly FieldDeclaration decimalConstantPattern = new FieldDeclaration { - Attributes = { - new AttributeSection { - Attributes = { - decimalConstantAttribute - } - } - }, - Modifiers = Modifiers.Any, - Variables = { new Repeat(new AnyNode()) }, - ReturnType = new PrimitiveType("decimal") - }; - - Expression ConstructExpression(string typeName, string member) - { - return new AssignmentExpression( - new MemberReferenceExpression( - new TypeReferenceExpression(new SimpleType(typeName)), - member - ), - AssignmentOperatorType.Assign, - new AnyNode() - ); - } - - class ClassInfo - { - public ClassInfo() - { - Fields = new List(); - } - - public List Fields { get; private set; } - public TypeDeclaration Declaration { get; set; } - } - - Stack replaceableFields; - - public DecimalConstantTransform() - { - } - - void IAstTransform.Run(AstNode compilationUnit) - { - this.replaceableFields = new Stack(); - compilationUnit.AcceptVisitor(this, null); - } + static readonly PrimitiveType decimalType = new PrimitiveType("decimal"); public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { - base.VisitFieldDeclaration(fieldDeclaration, data); - - var match = decimalConstantPattern.Match(fieldDeclaration); - - if (match.Success) { - Modifiers pattern = Modifiers.Static | Modifiers.Readonly; - if ((fieldDeclaration.Modifiers & pattern) == pattern) { - replaceableFields.Peek().Fields.AddRange(fieldDeclaration.Variables.Select(v => v.Name)); - fieldDeclaration.ReplaceWith(ReplaceFieldWithConstant); - } - } - - return null; - } - - AstNode ReplaceFieldWithConstant(AstNode node) - { - var old = node as FieldDeclaration; - var fd = new FieldDeclaration { - Modifiers = old.Modifiers & ~(Modifiers.Readonly | Modifiers.Static) | Modifiers.Const, - ReturnType = new PrimitiveType("decimal") - }; - - var foundAttr = old.Attributes.SelectMany(section => section.Attributes) - .First(a => decimalConstantAttribute.IsMatch(a)); - foundAttr.Remove(); - foreach (var attr in old.Attributes.Where(section => section.Attributes.Count == 0)) - attr.Remove(); - - old.Attributes.MoveTo(fd.Attributes); - old.Variables.MoveTo(fd.Variables); - - fd.Variables.Single().Initializer = new PrimitiveExpression(CreateDecimalValue(foundAttr)); - - return fd; - } - - object CreateDecimalValue(ICSharpCode.NRefactory.CSharp.Attribute foundAttr) - { - byte scale = (byte)((PrimitiveExpression)foundAttr.Arguments.ElementAt(0)).Value; - byte sign = (byte)((PrimitiveExpression)foundAttr.Arguments.ElementAt(1)).Value; - int high = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(2)).Value; - int mid = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(3)).Value; - int low = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(4)).Value; - - return new Decimal(low, mid, high, sign == 1, scale); - } - - public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) - { - if ((constructorDeclaration.Modifiers & Modifiers.Static) == Modifiers.Static && replaceableFields.Count > 0) { - var current = replaceableFields.Peek(); - - foreach (var fieldName in current.Fields) { - var pattern = ConstructExpression(current.Declaration.Name, fieldName); - foreach (var expr in constructorDeclaration.Body - .OfType()) { - if (pattern.IsMatch(expr.Expression)) - expr.Remove(); + const Modifiers staticReadOnly = Modifiers.Static | Modifiers.Readonly; + if ((fieldDeclaration.Modifiers & staticReadOnly) == staticReadOnly && decimalType.IsMatch(fieldDeclaration.ReturnType)) { + foreach (var attributeSection in fieldDeclaration.Attributes) { + foreach (var attribute in attributeSection.Attributes) { + TypeReference tr = attribute.Type.Annotation(); + if (tr != null && tr.Name == "DecimalConstantAttribute" && tr.Namespace == "System.Runtime.CompilerServices") { + attribute.Remove(); + if (attributeSection.Attributes.Count == 0) + attributeSection.Remove(); + fieldDeclaration.Modifiers = (fieldDeclaration.Modifiers & ~staticReadOnly) | Modifiers.Const; + return null; + } } } } - return null; } - public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + public void Run(AstNode compilationUnit) { - replaceableFields.Push(new ClassInfo() { Declaration = typeDeclaration }); - base.VisitTypeDeclaration(typeDeclaration, data); - replaceableFields.Pop(); - return null; + compilationUnit.AcceptVisitor(this, null); } } } diff --git a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs index 1433f0ef5..13730ea1d 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs @@ -32,7 +32,6 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public static IAstTransform[] CreatePipeline(DecompilerContext context) { return new IAstTransform[] { - new DecimalConstantTransform(), new PushNegation(), new DelegateConstruction(context), new PatternStatementTransform(context), @@ -41,6 +40,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms 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