diff options
Diffstat (limited to 'ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs')
-rw-r--r-- | ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs | 875 |
1 files changed, 0 insertions, 875 deletions
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs b/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs deleted file mode 100644 index 2327200d..00000000 --- a/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs +++ /dev/null @@ -1,875 +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.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using ICSharpCode.Decompiler.ILAst; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.PatternMatching; -using Mono.Cecil; - -namespace ICSharpCode.Decompiler.Ast.Transforms -{ - public class ExpressionTreeConverter - { - #region static TryConvert method - public static bool CouldBeExpressionTree(InvocationExpression expr) - { - if (expr != null && expr.Arguments.Count == 2) { - MethodReference mr = expr.Annotation<MethodReference>(); - return mr != null && mr.Name == "Lambda" && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression"; - } - return false; - } - - public static Expression TryConvert(DecompilerContext context, Expression expr) - { - Expression converted = new ExpressionTreeConverter(context).Convert(expr); - if (converted != null) { - converted.AddAnnotation(new ExpressionTreeLambdaAnnotation()); - } - return converted; - } - #endregion - - readonly DecompilerContext context; - Stack<LambdaExpression> activeLambdas = new Stack<LambdaExpression>(); - - ExpressionTreeConverter(DecompilerContext context) - { - this.context = context; - } - - #region Main Convert method - Expression Convert(Expression expr) - { - InvocationExpression invocation = expr as InvocationExpression; - if (invocation != null) { - MethodReference mr = invocation.Annotation<MethodReference>(); - if (mr != null && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression") { - switch (mr.Name) { - case "Add": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Add, false); - case "AddChecked": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Add, true); - case "AddAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Add, false); - case "AddAssignChecked": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Add, true); - case "And": - return ConvertBinaryOperator(invocation, BinaryOperatorType.BitwiseAnd); - case "AndAlso": - return ConvertBinaryOperator(invocation, BinaryOperatorType.ConditionalAnd); - case "AndAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.BitwiseAnd); - case "ArrayAccess": - case "ArrayIndex": - return ConvertArrayIndex(invocation); - case "ArrayLength": - return ConvertArrayLength(invocation); - case "Assign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Assign); - case "Call": - return ConvertCall(invocation); - case "Coalesce": - return ConvertBinaryOperator(invocation, BinaryOperatorType.NullCoalescing); - case "Condition": - return ConvertCondition(invocation); - case "Constant": - if (invocation.Arguments.Count >= 1) - return invocation.Arguments.First().Clone(); - else - return NotSupported(expr); - case "Convert": - return ConvertCast(invocation, false); - case "ConvertChecked": - return ConvertCast(invocation, true); - case "Divide": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Divide); - case "DivideAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Divide); - case "Equal": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Equality); - case "ExclusiveOr": - return ConvertBinaryOperator(invocation, BinaryOperatorType.ExclusiveOr); - case "ExclusiveOrAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ExclusiveOr); - case "Field": - return ConvertField(invocation); - case "GreaterThan": - return ConvertBinaryOperator(invocation, BinaryOperatorType.GreaterThan); - case "GreaterThanOrEqual": - return ConvertBinaryOperator(invocation, BinaryOperatorType.GreaterThanOrEqual); - case "Invoke": - return ConvertInvoke(invocation); - case "Lambda": - return ConvertLambda(invocation); - case "LeftShift": - return ConvertBinaryOperator(invocation, BinaryOperatorType.ShiftLeft); - case "LeftShiftAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ShiftLeft); - case "LessThan": - return ConvertBinaryOperator(invocation, BinaryOperatorType.LessThan); - case "LessThanOrEqual": - return ConvertBinaryOperator(invocation, BinaryOperatorType.LessThanOrEqual); - case "ListInit": - return ConvertListInit(invocation); - case "MemberInit": - return ConvertMemberInit(invocation); - case "Modulo": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Modulus); - case "ModuloAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Modulus); - case "Multiply": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Multiply, false); - case "MultiplyChecked": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Multiply, true); - case "MultiplyAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Multiply, false); - case "MultiplyAssignChecked": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Multiply, true); - case "Negate": - return ConvertUnaryOperator(invocation, UnaryOperatorType.Minus, false); - case "NegateChecked": - return ConvertUnaryOperator(invocation, UnaryOperatorType.Minus, true); - case "New": - return ConvertNewObject(invocation); - case "NewArrayBounds": - return ConvertNewArrayBounds(invocation); - case "NewArrayInit": - return ConvertNewArrayInit(invocation); - case "Not": - return ConvertUnaryOperator(invocation, UnaryOperatorType.Not); - case "NotEqual": - return ConvertBinaryOperator(invocation, BinaryOperatorType.InEquality); - case "OnesComplement": - return ConvertUnaryOperator(invocation, UnaryOperatorType.BitNot); - case "Or": - return ConvertBinaryOperator(invocation, BinaryOperatorType.BitwiseOr); - case "OrAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.BitwiseOr); - case "OrElse": - return ConvertBinaryOperator(invocation, BinaryOperatorType.ConditionalOr); - case "Property": - return ConvertProperty(invocation); - case "Quote": - if (invocation.Arguments.Count == 1) - return Convert(invocation.Arguments.Single()); - else - return NotSupported(invocation); - case "RightShift": - return ConvertBinaryOperator(invocation, BinaryOperatorType.ShiftRight); - case "RightShiftAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ShiftRight); - case "Subtract": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Subtract, false); - case "SubtractChecked": - return ConvertBinaryOperator(invocation, BinaryOperatorType.Subtract, true); - case "SubtractAssign": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Subtract, false); - case "SubtractAssignChecked": - return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Subtract, true); - case "TypeAs": - return ConvertTypeAs(invocation); - case "TypeIs": - return ConvertTypeIs(invocation); - } - } - } - IdentifierExpression ident = expr as IdentifierExpression; - if (ident != null) { - ILVariable v = ident.Annotation<ILVariable>(); - if (v != null) { - foreach (LambdaExpression lambda in activeLambdas) { - foreach (ParameterDeclaration p in lambda.Parameters) { - if (p.Annotation<ILVariable>() == v) - return new IdentifierExpression(p.Name).WithAnnotation(v); - } - } - } - } - return NotSupported(expr); - } - - Expression NotSupported(Expression expr) - { - Debug.WriteLine("Expression Tree Conversion Failed: '" + expr + "' is not supported"); - return null; - } - #endregion - - #region Convert Lambda - static readonly Expression emptyArrayPattern = new ArrayCreateExpression { - Type = new AnyNode(), - Arguments = { new PrimitiveExpression(0) } - }; - - Expression ConvertLambda(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - LambdaExpression lambda = new LambdaExpression(); - Expression body = invocation.Arguments.First(); - ArrayCreateExpression parameterArray = invocation.Arguments.Last() as ArrayCreateExpression; - if (parameterArray == null) - return NotSupported(invocation); - - var annotation = body.Annotation<ParameterDeclarationAnnotation>(); - if (annotation != null) { - lambda.Parameters.AddRange(annotation.Parameters); - } else { - // No parameter declaration annotation found. - if (!emptyArrayPattern.IsMatch(parameterArray)) - return null; - } - - activeLambdas.Push(lambda); - Expression convertedBody = Convert(body); - activeLambdas.Pop(); - if (convertedBody == null) - return null; - lambda.Body = convertedBody; - return lambda; - } - #endregion - - #region Convert Field - static readonly Expression getFieldFromHandlePattern = - new TypePattern(typeof(FieldInfo)).ToType().Invoke( - "GetFieldFromHandle", - new LdTokenPattern("field").ToExpression().Member("FieldHandle"), - new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle")) - ); - - Expression ConvertField(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - - Expression fieldInfoExpr = invocation.Arguments.ElementAt(1); - Match m = getFieldFromHandlePattern.Match(fieldInfoExpr); - if (!m.Success) - return NotSupported(invocation); - - FieldReference fr = m.Get<AstNode>("field").Single().Annotation<FieldReference>(); - if (fr == null) - return null; - - Expression target = invocation.Arguments.ElementAt(0); - Expression convertedTarget; - if (target is NullReferenceExpression) { - if (m.Has("declaringType")) - convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone()); - else - convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(fr.DeclaringType)); - } else { - convertedTarget = Convert(target); - if (convertedTarget == null) - return null; - } - - return convertedTarget.Member(fr.Name).WithAnnotation(fr); - } - #endregion - - #region Convert Property - static readonly Expression getMethodFromHandlePattern = - new TypePattern(typeof(MethodBase)).ToType().Invoke( - "GetMethodFromHandle", - new LdTokenPattern("method").ToExpression().Member("MethodHandle"), - new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle")) - ).CastTo(new TypePattern(typeof(MethodInfo))); - - Expression ConvertProperty(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - - Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1)); - if (!m.Success) - return NotSupported(invocation); - - MethodReference mr = m.Get<AstNode>("method").Single().Annotation<MethodReference>(); - if (mr == null) - return null; - - Expression target = invocation.Arguments.ElementAt(0); - Expression convertedTarget; - if (target is NullReferenceExpression) { - if (m.Has("declaringType")) - convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone()); - else - convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(mr.DeclaringType)); - } else { - convertedTarget = Convert(target); - if (convertedTarget == null) - return null; - } - - return convertedTarget.Member(GetPropertyName(mr)).WithAnnotation(mr); - } - - string GetPropertyName(MethodReference accessor) - { - string name = accessor.Name; - if (name.StartsWith("get_", StringComparison.Ordinal) || name.StartsWith("set_", StringComparison.Ordinal)) - name = name.Substring(4); - return name; - } - #endregion - - #region Convert Call - Expression ConvertCall(InvocationExpression invocation) - { - if (invocation.Arguments.Count < 2) - return NotSupported(invocation); - - Expression target; - int firstArgumentPosition; - - Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(0)); - if (m.Success) { - target = null; - firstArgumentPosition = 1; - } else { - m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1)); - if (!m.Success) - return NotSupported(invocation); - target = invocation.Arguments.ElementAt(0); - firstArgumentPosition = 2; - } - - MethodReference mr = m.Get<AstNode>("method").Single().Annotation<MethodReference>(); - if (mr == null) - return null; - - Expression convertedTarget; - if (target == null || target is NullReferenceExpression) { - // static method - if (m.Has("declaringType")) - convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone()); - else - convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(mr.DeclaringType)); - } else { - convertedTarget = Convert(target); - if (convertedTarget == null) - return null; - } - - MemberReferenceExpression mre = convertedTarget.Member(mr.Name); - GenericInstanceMethod gim = mr as GenericInstanceMethod; - if (gim != null) { - foreach (TypeReference tr in gim.GenericArguments) { - mre.TypeArguments.Add(AstBuilder.ConvertType(tr)); - } - } - IList<Expression> arguments = null; - if (invocation.Arguments.Count == firstArgumentPosition + 1) { - Expression argumentArray = invocation.Arguments.ElementAt(firstArgumentPosition); - arguments = ConvertExpressionsArray(argumentArray); - } - if (arguments == null) { - arguments = new List<Expression>(); - foreach (Expression argument in invocation.Arguments.Skip(firstArgumentPosition)) { - Expression convertedArgument = Convert(argument); - if (convertedArgument == null) - return null; - arguments.Add(convertedArgument); - } - } - MethodDefinition methodDef = mr.Resolve(); - if (methodDef != null && methodDef.IsGetter) { - PropertyDefinition indexer = AstMethodBodyBuilder.GetIndexer(methodDef); - if (indexer != null) - return new IndexerExpression(mre.Target.Detach(), arguments).WithAnnotation(indexer); - } - return new InvocationExpression(mre, arguments).WithAnnotation(mr); - } - - Expression ConvertInvoke(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - - Expression convertedTarget = Convert(invocation.Arguments.ElementAt(0)); - IList<Expression> convertedArguments = ConvertExpressionsArray(invocation.Arguments.ElementAt(1)); - if (convertedTarget != null && convertedArguments != null) - return new InvocationExpression(convertedTarget, convertedArguments); - else - return null; - } - #endregion - - #region Convert Binary Operator - static readonly Pattern trueOrFalse = new Choice { - new PrimitiveExpression(true), - new PrimitiveExpression(false) - }; - - Expression ConvertBinaryOperator(InvocationExpression invocation, BinaryOperatorType op, bool? isChecked = null) - { - if (invocation.Arguments.Count < 2) - return NotSupported(invocation); - - Expression left = Convert(invocation.Arguments.ElementAt(0)); - if (left == null) - return null; - Expression right = Convert(invocation.Arguments.ElementAt(1)); - if (right == null) - return null; - - BinaryOperatorExpression boe = new BinaryOperatorExpression(left, op, right); - if (isChecked != null) - boe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); - - switch (invocation.Arguments.Count) { - case 2: - return boe; - case 3: - Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2)); - if (m.Success) - return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>()); - else - return null; - case 4: - if (!trueOrFalse.IsMatch(invocation.Arguments.ElementAt(2))) - return null; - m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(3)); - if (m.Success) - return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>()); - else - return null; - default: - return NotSupported(invocation); - } - } - #endregion - - #region Convert Assignment Operator - Expression ConvertAssignmentOperator(InvocationExpression invocation, AssignmentOperatorType op, bool? isChecked = null) - { - return NotSupported(invocation); - } - #endregion - - #region Convert Unary Operator - Expression ConvertUnaryOperator(InvocationExpression invocation, UnaryOperatorType op, bool? isChecked = null) - { - if (invocation.Arguments.Count < 1) - return NotSupported(invocation); - - Expression expr = Convert(invocation.Arguments.ElementAt(0)); - if (expr == null) - return null; - - UnaryOperatorExpression uoe = new UnaryOperatorExpression(op, expr); - if (isChecked != null) - uoe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); - - switch (invocation.Arguments.Count) { - case 1: - return uoe; - case 2: - Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1)); - if (m.Success) - return uoe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>()); - else - return null; - default: - return NotSupported(invocation); - } - } - #endregion - - #region Convert Condition Operator - Expression ConvertCondition(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 3) - return NotSupported(invocation); - - Expression condition = Convert(invocation.Arguments.ElementAt(0)); - Expression trueExpr = Convert(invocation.Arguments.ElementAt(1)); - Expression falseExpr = Convert(invocation.Arguments.ElementAt(2)); - if (condition != null && trueExpr != null && falseExpr != null) - return new ConditionalExpression(condition, trueExpr, falseExpr); - else - return null; - } - #endregion - - #region Convert New Object - static readonly Expression newObjectCtorPattern = new TypePattern(typeof(MethodBase)).ToType().Invoke - ( - "GetMethodFromHandle", - new LdTokenPattern("ctor").ToExpression().Member("MethodHandle"), - new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle")) - ).CastTo(new TypePattern(typeof(ConstructorInfo))); - - Expression ConvertNewObject(InvocationExpression invocation) - { - if (invocation.Arguments.Count < 1 || invocation.Arguments.Count > 3) - return NotSupported(invocation); - - Match m = newObjectCtorPattern.Match(invocation.Arguments.First()); - if (!m.Success) - return NotSupported(invocation); - - MethodReference ctor = m.Get<AstNode>("ctor").Single().Annotation<MethodReference>(); - if (ctor == null) - return null; - - AstType declaringTypeNode; - TypeReference declaringType; - if (m.Has("declaringType")) { - declaringTypeNode = m.Get<AstType>("declaringType").Single().Clone(); - declaringType = declaringTypeNode.Annotation<TypeReference>(); - } else { - declaringTypeNode = AstBuilder.ConvertType(ctor.DeclaringType); - declaringType = ctor.DeclaringType; - } - if (declaringTypeNode == null) - return null; - - ObjectCreateExpression oce = new ObjectCreateExpression(declaringTypeNode); - if (invocation.Arguments.Count >= 2) { - IList<Expression> arguments = ConvertExpressionsArray(invocation.Arguments.ElementAtOrDefault(1)); - if (arguments == null) - return null; - oce.Arguments.AddRange(arguments); - } - if (invocation.Arguments.Count >= 3 && declaringType.IsAnonymousType()) { - MethodDefinition resolvedCtor = ctor.Resolve(); - if (resolvedCtor == null || resolvedCtor.Parameters.Count != oce.Arguments.Count) - return null; - AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); - var arguments = oce.Arguments.ToArray(); - if (AstMethodBodyBuilder.CanInferAnonymousTypePropertyNamesFromArguments(arguments, resolvedCtor.Parameters)) { - oce.Arguments.MoveTo(atce.Initializers); - } else { - for (int i = 0; i < resolvedCtor.Parameters.Count; i++) { - atce.Initializers.Add( - new NamedExpression { - Name = resolvedCtor.Parameters[i].Name, - Expression = arguments[i].Detach() - }); - } - } - return atce; - } - - return oce; - } - #endregion - - #region Convert ListInit - static readonly Pattern elementInitArrayPattern = ArrayInitializationPattern( - typeof(System.Linq.Expressions.ElementInit), - new TypePattern(typeof(System.Linq.Expressions.Expression)).ToType().Invoke("ElementInit", new AnyNode("methodInfos"), new AnyNode("addArgumentsArrays")) - ); - - Expression ConvertListInit(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - ObjectCreateExpression oce = Convert(invocation.Arguments.ElementAt(0)) as ObjectCreateExpression; - if (oce == null) - return null; - Expression elementsArray = invocation.Arguments.ElementAt(1); - ArrayInitializerExpression initializer = ConvertElementInit(elementsArray); - if (initializer != null) { - oce.Initializer = initializer; - return oce; - } else { - return null; - } - } - - ArrayInitializerExpression ConvertElementInit(Expression elementsArray) - { - IList<Expression> elements = ConvertExpressionsArray(elementsArray); - if (elements != null) { - return new ArrayInitializerExpression(elements); - } - Match m = elementInitArrayPattern.Match(elementsArray); - if (!m.Success) - return null; - ArrayInitializerExpression result = new ArrayInitializerExpression(); - foreach (var elementInit in m.Get<Expression>("addArgumentsArrays")) { - IList<Expression> arguments = ConvertExpressionsArray(elementInit); - if (arguments == null) - return null; - result.Elements.Add(new ArrayInitializerExpression(arguments)); - } - return result; - } - #endregion - - #region Convert MemberInit - Expression ConvertMemberInit(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - ObjectCreateExpression oce = Convert(invocation.Arguments.ElementAt(0)) as ObjectCreateExpression; - if (oce == null) - return null; - Expression elementsArray = invocation.Arguments.ElementAt(1); - ArrayInitializerExpression bindings = ConvertMemberBindings(elementsArray); - if (bindings == null) - return null; - oce.Initializer = bindings; - return oce; - } - - static readonly Pattern memberBindingArrayPattern = ArrayInitializationPattern(typeof(System.Linq.Expressions.MemberBinding), new AnyNode("binding")); - static readonly INode expressionTypeReference = new TypeReferenceExpression(new TypePattern(typeof(System.Linq.Expressions.Expression))); - - ArrayInitializerExpression ConvertMemberBindings(Expression elementsArray) - { - Match m = memberBindingArrayPattern.Match(elementsArray); - if (!m.Success) - return null; - ArrayInitializerExpression result = new ArrayInitializerExpression(); - foreach (var binding in m.Get<Expression>("binding")) { - InvocationExpression bindingInvocation = binding as InvocationExpression; - if (bindingInvocation == null || bindingInvocation.Arguments.Count != 2) - return null; - MemberReferenceExpression bindingMRE = bindingInvocation.Target as MemberReferenceExpression; - if (bindingMRE == null || !expressionTypeReference.IsMatch(bindingMRE.Target)) - return null; - - Expression bindingTarget = bindingInvocation.Arguments.ElementAt(0); - Expression bindingValue = bindingInvocation.Arguments.ElementAt(1); - - string memberName; - Match m2 = getMethodFromHandlePattern.Match(bindingTarget); - if (m2.Success) { - MethodReference setter = m2.Get<AstNode>("method").Single().Annotation<MethodReference>(); - if (setter == null) - return null; - memberName = GetPropertyName(setter); - } else { - return null; - } - - Expression convertedValue; - switch (bindingMRE.MemberName) { - case "Bind": - convertedValue = Convert(bindingValue); - break; - case "MemberBind": - convertedValue = ConvertMemberBindings(bindingValue); - break; - case "ListBind": - convertedValue = ConvertElementInit(bindingValue); - break; - default: - return null; - } - if (convertedValue == null) - return null; - result.Elements.Add(new NamedExpression(memberName, convertedValue)); - } - return result; - } - #endregion - - #region Convert Cast - Expression ConvertCast(InvocationExpression invocation, bool isChecked) - { - if (invocation.Arguments.Count < 2) - return null; - Expression converted = Convert(invocation.Arguments.ElementAt(0)); - AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1)); - if (converted != null && type != null) { - CastExpression cast = converted.CastTo(type); - cast.AddAnnotation(isChecked ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); - switch (invocation.Arguments.Count) { - case 2: - return cast; - case 3: - Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2)); - if (m.Success) - return cast.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>()); - else - return null; - } - } - return null; - } - #endregion - - #region ConvertExpressionsArray - static Pattern ArrayInitializationPattern(Type arrayElementType, INode elementPattern) - { - return new Choice { - new ArrayCreateExpression { - Type = new TypePattern(arrayElementType), - Arguments = { new PrimitiveExpression(0) } - }, - new ArrayCreateExpression { - Type = new TypePattern(arrayElementType), - AdditionalArraySpecifiers = { new ArraySpecifier() }, - Initializer = new ArrayInitializerExpression { - Elements = { new Repeat(elementPattern) } - } - } - }; - } - - static readonly Pattern expressionArrayPattern = ArrayInitializationPattern(typeof(System.Linq.Expressions.Expression), new AnyNode("elements")); - - IList<Expression> ConvertExpressionsArray(Expression arrayExpression) - { - Match m = expressionArrayPattern.Match(arrayExpression); - if (m.Success) { - List<Expression> result = new List<Expression>(); - foreach (Expression expr in m.Get<Expression>("elements")) { - Expression converted = Convert(expr); - if (converted == null) - return null; - result.Add(converted); - } - return result; - } - return null; - } - #endregion - - #region Convert TypeAs/TypeIs - static readonly TypeOfPattern typeOfPattern = new TypeOfPattern("type"); - - AstType ConvertTypeReference(Expression typeOfExpression) - { - Match m = typeOfPattern.Match(typeOfExpression); - if (m.Success) - return m.Get<AstType>("type").Single().Clone(); - else - return null; - } - - Expression ConvertTypeAs(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return null; - Expression converted = Convert(invocation.Arguments.ElementAt(0)); - AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1)); - if (converted != null && type != null) - return new AsExpression(converted, type); - return null; - } - - Expression ConvertTypeIs(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return null; - Expression converted = Convert(invocation.Arguments.ElementAt(0)); - AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1)); - if (converted != null && type != null) - return new IsExpression { Expression = converted, Type = type }; - return null; - } - #endregion - - #region Convert Array - Expression ConvertArrayIndex(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - - Expression targetConverted = Convert(invocation.Arguments.First()); - if (targetConverted == null) - return null; - - Expression index = invocation.Arguments.ElementAt(1); - Expression indexConverted = Convert(index); - if (indexConverted != null) { - return new IndexerExpression(targetConverted, indexConverted); - } - IList<Expression> indexesConverted = ConvertExpressionsArray(index); - if (indexesConverted != null) { - return new IndexerExpression(targetConverted, indexesConverted); - } - return null; - } - - Expression ConvertArrayLength(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 1) - return NotSupported(invocation); - - Expression targetConverted = Convert(invocation.Arguments.Single()); - if (targetConverted != null) - return targetConverted.Member("Length"); - else - return null; - } - - Expression ConvertNewArrayInit(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - - AstType elementType = ConvertTypeReference(invocation.Arguments.ElementAt(0)); - IList<Expression> elements = ConvertExpressionsArray(invocation.Arguments.ElementAt(1)); - if (elementType != null && elements != null) { - if (ContainsAnonymousType(elementType)) { - elementType = null; - } - return new ArrayCreateExpression { - Type = elementType, - AdditionalArraySpecifiers = { new ArraySpecifier() }, - Initializer = new ArrayInitializerExpression(elements) - }; - } - return null; - } - - Expression ConvertNewArrayBounds(InvocationExpression invocation) - { - if (invocation.Arguments.Count != 2) - return NotSupported(invocation); - - AstType elementType = ConvertTypeReference(invocation.Arguments.ElementAt(0)); - IList<Expression> arguments = ConvertExpressionsArray(invocation.Arguments.ElementAt(1)); - if (elementType != null && arguments != null) { - if (ContainsAnonymousType(elementType)) { - elementType = null; - } - ArrayCreateExpression ace = new ArrayCreateExpression(); - ace.Type = elementType; - ace.Arguments.AddRange(arguments); - return ace; - } - return null; - } - - bool ContainsAnonymousType(AstType type) - { - foreach (AstType t in type.DescendantsAndSelf.OfType<AstType>()) { - TypeReference tr = t.Annotation<TypeReference>(); - if (tr != null && tr.IsAnonymousType()) - return true; - } - return false; - } - #endregion - } -} |