diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index ddc9e8ca0..203a68a72 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -278,7 +278,7 @@ namespace Decompiler } } - string FormatByteCodeOperand(object operand) + static string FormatByteCodeOperand(object operand) { if (operand == null) { return string.Empty; diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs b/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs index 1bc4ad36b..0a9d943ee 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs @@ -114,7 +114,7 @@ namespace Decompiler.Transforms negate = true; } if (m != null) { - Expression expr = ((Expression)m["expr"].Single()).Detach().IsType((AstType)m["type"].Single().Detach()); + Expression expr = m.Get("expr").Single().Detach().IsType(m.Get("type").Single().Detach()); if (negate) expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr); binaryOperatorExpression.ReplaceWith(expr); diff --git a/ICSharpCode.Decompiler/Ast/Transforms/UsingStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/UsingStatementTransform.cs index 453c7a84a..780a2ed18 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/UsingStatementTransform.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/UsingStatementTransform.cs @@ -6,6 +6,7 @@ using System.Linq; using Decompiler.Transforms; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.PatternMatching; +using Mono.Cecil; namespace Decompiler.Transforms { @@ -29,18 +30,25 @@ namespace Decompiler.Transforms TryBlock = new AnyNode("body").ToBlock(), FinallyBlock = new BlockStatement { Statements = { - new IfElseStatement { - Condition = new BinaryOperatorExpression( - new NamedNode("ident", new IdentifierExpression()).ToExpression(), - BinaryOperatorType.InEquality, - new NullReferenceExpression() - ), - TrueStatement = new BlockStatement { - Statements = { - new ExpressionStatement(new Backreference("ident").ToExpression().Invoke("Dispose")) + new Choice { + { "valueType", + new ExpressionStatement(new NamedNode("ident", new IdentifierExpression()).ToExpression().Invoke("Dispose")) + }, + { "referenceType", + new IfElseStatement { + Condition = new BinaryOperatorExpression( + new NamedNode("ident", new IdentifierExpression()).ToExpression(), + BinaryOperatorType.InEquality, + new NullReferenceExpression() + ), + TrueStatement = new BlockStatement { + Statements = { + new ExpressionStatement(new Backreference("ident").ToExpression().Invoke("Dispose")) + } + } } } - } + }.ToStatement() } } }; @@ -52,8 +60,14 @@ namespace Decompiler.Transforms if (m1 == null) continue; Match m2 = usingTryCatchPattern.Match(node.NextSibling); if (m2 == null) continue; - if (((VariableInitializer)m1["variable"].Single()).Name == ((IdentifierExpression)m2["ident"].Single()).Identifier) { - BlockStatement body = (BlockStatement)m2["body"].Single(); + if (m1.Get("variable").Single().Name == m2.Get("ident").Single().Identifier) { + if (m2.Has("valueType")) { + // if there's no if(x!=null), then it must be a value type + TypeReference tr = m1.Get("type").Single().Annotation(); + if (tr == null || !tr.IsValueType) + continue; + } + BlockStatement body = m2.Get("body").Single(); body.Remove(); node.NextSibling.Remove(); node.ReplaceWith( diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Backreference.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Backreference.cs index c5573f01a..db3e3eceb 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Backreference.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Backreference.cs @@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching protected internal override bool DoMatch(AstNode other, Match match) { - return match[referencedGroupName].Last().Match(other) != null; + return match.Get(referencedGroupName).Last().Match(other) != null; } } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Choice.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Choice.cs index ba0954884..6435cc324 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Choice.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Choice.cs @@ -2,20 +2,25 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Collections; namespace ICSharpCode.NRefactory.CSharp.PatternMatching { /// /// Matches one of several alternatives. /// - public class Choice : Pattern + public class Choice : Pattern, IEnumerable { public static readonly Role AlternativeRole = new Role("Alternative", AstNode.Null); - public Choice(params AstNode[] alternatives) + public void Add(string name, AstNode alternative) { - foreach (AstNode node in alternatives) - AddChild(node, AlternativeRole); + AddChild(new NamedNode(name, alternative), AlternativeRole); + } + + public void Add(AstNode alternative) + { + AddChild(alternative, AlternativeRole); } protected internal override bool DoMatch(AstNode other, Match match) @@ -29,5 +34,10 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching } return false; } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetChildrenByRole(AlternativeRole).GetEnumerator(); + } } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs index 4a44dc36f..9b1ff905f 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs @@ -24,13 +24,29 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching results.RemoveRange(checkPoint, results.Count - checkPoint); } - public IEnumerable this[string groupName] { - get { - foreach (var pair in results) { - if (pair.Key == groupName) - yield return pair.Value; - } + public IEnumerable Get(string groupName) + { + foreach (var pair in results) { + if (pair.Key == groupName) + yield return pair.Value; + } + } + + public IEnumerable Get(string groupName) where T : AstNode + { + foreach (var pair in results) { + if (pair.Key == groupName) + yield return (T)pair.Value; + } + } + + public bool Has(string groupName) + { + foreach (var pair in results) { + if (pair.Key == groupName) + return true; } + return false; } public void Add(string groupName, AstNode node) diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs index 794806a86..2e08092a9 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs @@ -29,6 +29,11 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching return new ExpressionPlaceholder(this); } + public Statement ToStatement() + { + return new StatementPlaceholder(this); + } + public BlockStatement ToBlock() { return new BlockStatementPlaceholder(this); diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs index 16ca73cef..f84faaa39 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs @@ -7,113 +7,113 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching { sealed class TypePlaceholder : AstType { - public static readonly Role PatternRole = new Role("Pattern"); + public static readonly Role ChildRole = new Role("Child", AstNode.Null); - public TypePlaceholder(Pattern pattern) + public TypePlaceholder(AstNode child) { - AddChild(pattern, TypePlaceholder.PatternRole); + AddChild(child, TypePlaceholder.ChildRole); } public override NodeType NodeType { - get { return NodeType.Pattern; } + get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; } } public override S AcceptVisitor(IAstVisitor visitor, T data) { - return default(S); + return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); + return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match); } } sealed class ExpressionPlaceholder : Expression { - public ExpressionPlaceholder(Pattern pattern) + public ExpressionPlaceholder(AstNode child) { - AddChild(pattern, TypePlaceholder.PatternRole); + AddChild(child, TypePlaceholder.ChildRole); } public override NodeType NodeType { - get { return NodeType.Pattern; } + get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; } } public override S AcceptVisitor(IAstVisitor visitor, T data) { - return default(S); + return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); + return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match); } } sealed class StatementPlaceholder : Statement { - public StatementPlaceholder(Pattern pattern) + public StatementPlaceholder(AstNode child) { - AddChild(pattern, TypePlaceholder.PatternRole); + AddChild(child, TypePlaceholder.ChildRole); } public override NodeType NodeType { - get { return NodeType.Pattern; } + get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; } } public override S AcceptVisitor(IAstVisitor visitor, T data) { - return default(S); + return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); + return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match); } } sealed class BlockStatementPlaceholder : BlockStatement { - public BlockStatementPlaceholder(Pattern pattern) + public BlockStatementPlaceholder(AstNode child) { - AddChild(pattern, TypePlaceholder.PatternRole); + AddChild(child, TypePlaceholder.ChildRole); } public override NodeType NodeType { - get { return NodeType.Pattern; } + get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; } } public override S AcceptVisitor(IAstVisitor visitor, T data) { - return default(S); + return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); + return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match); } } sealed class VariablePlaceholder : VariableInitializer { - public VariablePlaceholder(Pattern pattern) + public VariablePlaceholder(AstNode child) { - AddChild(pattern, TypePlaceholder.PatternRole); + AddChild(child, TypePlaceholder.ChildRole); } public override NodeType NodeType { - get { return NodeType.Pattern; } + get { return GetChildByRole(TypePlaceholder.ChildRole).NodeType; } } public override S AcceptVisitor(IAstVisitor visitor, T data) { - return default(S); + return GetChildByRole(TypePlaceholder.ChildRole).AcceptVisitor(visitor, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); + return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, match); } } }