Пример #1
0
        internal static Expression Create(ExpressionNodeInfo info)
        {
            // Some expressions can be extremely deep (e.g. string + string + string ...)
            // to the extent that the stack has been known to overflow.
            using (info.Context.StackGuard)
            {
                if (info.Node == null)
                {
                    info.Context.ModelError("Attempt to create a null expression");
                    return(new Unknown(info));
                }

                switch (info.Node.Kind())
                {
                case SyntaxKind.AddExpression:
                case SyntaxKind.SubtractExpression:
                case SyntaxKind.LessThanExpression:
                case SyntaxKind.LessThanOrEqualExpression:
                case SyntaxKind.GreaterThanExpression:
                case SyntaxKind.GreaterThanOrEqualExpression:
                case SyntaxKind.MultiplyExpression:
                case SyntaxKind.LogicalAndExpression:
                case SyntaxKind.EqualsExpression:
                case SyntaxKind.ModuloExpression:
                case SyntaxKind.BitwiseAndExpression:
                case SyntaxKind.BitwiseOrExpression:
                case SyntaxKind.DivideExpression:
                case SyntaxKind.NotEqualsExpression:
                case SyntaxKind.LogicalOrExpression:
                case SyntaxKind.IsExpression:
                case SyntaxKind.AsExpression:
                case SyntaxKind.RightShiftExpression:
                case SyntaxKind.LeftShiftExpression:
                case SyntaxKind.ExclusiveOrExpression:
                case SyntaxKind.CoalesceExpression:
                    return(Binary.Create(info));

                case SyntaxKind.FalseLiteralExpression:
                case SyntaxKind.TrueLiteralExpression:
                case SyntaxKind.StringLiteralExpression:
                case SyntaxKind.NullLiteralExpression:
                case SyntaxKind.NumericLiteralExpression:
                case SyntaxKind.CharacterLiteralExpression:
                case SyntaxKind.DefaultLiteralExpression:
                    return(Literal.Create(info));

                case SyntaxKind.InvocationExpression:
                    return(Invocation.Create(info));

                case SyntaxKind.PostIncrementExpression:
                    return(PostfixUnary.Create(info.SetKind(ExprKind.POST_INCR), ((PostfixUnaryExpressionSyntax)info.Node).Operand));

                case SyntaxKind.PostDecrementExpression:
                    return(PostfixUnary.Create(info.SetKind(ExprKind.POST_DECR), ((PostfixUnaryExpressionSyntax)info.Node).Operand));

                case SyntaxKind.AwaitExpression:
                    return(Await.Create(info));

                case SyntaxKind.ElementAccessExpression:
                    return(NormalElementAccess.Create(info));

                case SyntaxKind.SimpleAssignmentExpression:
                case SyntaxKind.OrAssignmentExpression:
                case SyntaxKind.AndAssignmentExpression:
                case SyntaxKind.SubtractAssignmentExpression:
                case SyntaxKind.AddAssignmentExpression:
                case SyntaxKind.MultiplyAssignmentExpression:
                case SyntaxKind.ExclusiveOrAssignmentExpression:
                case SyntaxKind.LeftShiftAssignmentExpression:
                case SyntaxKind.RightShiftAssignmentExpression:
                case SyntaxKind.DivideAssignmentExpression:
                case SyntaxKind.ModuloAssignmentExpression:
                case SyntaxKind.CoalesceAssignmentExpression:
                    return(Assignment.Create(info));

                case SyntaxKind.ObjectCreationExpression:
                    return(ExplicitObjectCreation.Create(info));

                case SyntaxKind.ArrayCreationExpression:
                    return(NormalArrayCreation.Create(info));

                case SyntaxKind.ObjectInitializerExpression:
                    return(ObjectInitializer.Create(info));

                case SyntaxKind.ArrayInitializerExpression:
                    return(ImplicitArrayInitializer.Create(info));

                case SyntaxKind.CollectionInitializerExpression:
                    return(CollectionInitializer.Create(info));

                case SyntaxKind.ConditionalAccessExpression:
                    return(MemberAccess.Create(info, (ConditionalAccessExpressionSyntax)info.Node));

                case SyntaxKind.SimpleMemberAccessExpression:
                    return(MemberAccess.Create(info, (MemberAccessExpressionSyntax)info.Node));

                case SyntaxKind.UnaryMinusExpression:
                    return(Unary.Create(info.SetKind(ExprKind.MINUS)));

                case SyntaxKind.UnaryPlusExpression:
                    return(Unary.Create(info.SetKind(ExprKind.PLUS)));

                case SyntaxKind.SimpleLambdaExpression:
                    return(Lambda.Create(info, (SimpleLambdaExpressionSyntax)info.Node));

                case SyntaxKind.ParenthesizedLambdaExpression:
                    return(Lambda.Create(info, (ParenthesizedLambdaExpressionSyntax)info.Node));

                case SyntaxKind.ConditionalExpression:
                    return(Conditional.Create(info));

                case SyntaxKind.CastExpression:
                    return(Cast.Create(info));

                case SyntaxKind.ParenthesizedExpression:
                    return(Create(info.SetNode(((ParenthesizedExpressionSyntax)info.Node).Expression)));

                case SyntaxKind.PointerType:
                case SyntaxKind.ArrayType:
                case SyntaxKind.PredefinedType:
                case SyntaxKind.NullableType:
                case SyntaxKind.TupleType:
                    return(TypeAccess.Create(info));

                case SyntaxKind.TypeOfExpression:
                    return(TypeOf.Create(info));

                case SyntaxKind.QualifiedName:
                case SyntaxKind.IdentifierName:
                case SyntaxKind.AliasQualifiedName:
                case SyntaxKind.GenericName:
                    return(Name.Create(info));

                case SyntaxKind.LogicalNotExpression:
                    return(Unary.Create(info.SetKind(ExprKind.LOG_NOT)));

                case SyntaxKind.BitwiseNotExpression:
                    return(Unary.Create(info.SetKind(ExprKind.BIT_NOT)));

                case SyntaxKind.PreIncrementExpression:
                    return(Unary.Create(info.SetKind(ExprKind.PRE_INCR)));

                case SyntaxKind.PreDecrementExpression:
                    return(Unary.Create(info.SetKind(ExprKind.PRE_DECR)));

                case SyntaxKind.ThisExpression:
                    return(This.CreateExplicit(info));

                case SyntaxKind.AddressOfExpression:
                    return(Unary.Create(info.SetKind(ExprKind.ADDRESS_OF)));

                case SyntaxKind.PointerIndirectionExpression:
                    return(Unary.Create(info.SetKind(ExprKind.POINTER_INDIRECTION)));

                case SyntaxKind.DefaultExpression:
                    return(Default.Create(info));

                case SyntaxKind.CheckedExpression:
                    return(Checked.Create(info));

                case SyntaxKind.UncheckedExpression:
                    return(Unchecked.Create(info));

                case SyntaxKind.BaseExpression:
                    return(Base.Create(info));

                case SyntaxKind.AnonymousMethodExpression:
                    return(Lambda.Create(info, (AnonymousMethodExpressionSyntax)info.Node));

                case SyntaxKind.ImplicitArrayCreationExpression:
                    return(ImplicitArrayCreation.Create(info));

                case SyntaxKind.AnonymousObjectCreationExpression:
                    return(ImplicitObjectCreation.Create(info));

                case SyntaxKind.ComplexElementInitializerExpression:
                    return(CollectionInitializer.Create(info));

                case SyntaxKind.SizeOfExpression:
                    return(SizeOf.Create(info));

                case SyntaxKind.PointerMemberAccessExpression:
                    return(PointerMemberAccess.Create(info));

                case SyntaxKind.QueryExpression:
                    return(Query.Create(info));

                case SyntaxKind.InterpolatedStringExpression:
                    return(InterpolatedString.Create(info));

                case SyntaxKind.MemberBindingExpression:
                    return(MemberAccess.Create(info, (MemberBindingExpressionSyntax)info.Node));

                case SyntaxKind.ElementBindingExpression:
                    return(BindingElementAccess.Create(info));

                case SyntaxKind.StackAllocArrayCreationExpression:
                    return(StackAllocArrayCreation.Create(info));

                case SyntaxKind.ImplicitStackAllocArrayCreationExpression:
                    return(ImplicitStackAllocArrayCreation.Create(info));

                case SyntaxKind.ArgListExpression:
                    return(ArgList.Create(info));

                case SyntaxKind.RefTypeExpression:
                    return(RefType.Create(info));

                case SyntaxKind.RefValueExpression:
                    return(RefValue.Create(info));

                case SyntaxKind.MakeRefExpression:
                    return(MakeRef.Create(info));

                case SyntaxKind.ThrowExpression:
                    return(Throw.Create(info));

                case SyntaxKind.DeclarationExpression:
                    return(VariableDeclaration.Create(info.Context, (DeclarationExpressionSyntax)info.Node, info.Parent, info.Child));

                case SyntaxKind.TupleExpression:
                    return(Tuple.Create(info));

                case SyntaxKind.RefExpression:
                    return(Ref.Create(info));

                case SyntaxKind.IsPatternExpression:
                    return(IsPattern.Create(info));

                case SyntaxKind.RangeExpression:
                    return(RangeExpression.Create(info));

                case SyntaxKind.IndexExpression:
                    return(Unary.Create(info.SetKind(ExprKind.INDEX)));

                case SyntaxKind.SwitchExpression:
                    return(Switch.Create(info));

                case SyntaxKind.SuppressNullableWarningExpression:
                    return(PostfixUnary.Create(info.SetKind(ExprKind.SUPPRESS_NULLABLE_WARNING), ((PostfixUnaryExpressionSyntax)info.Node).Operand));

                default:
                    info.Context.ModelError(info.Node, $"Unhandled expression '{info.Node}' of kind '{info.Node.Kind()}'");
                    return(new Unknown(info));
                }
            }
        }
Пример #2
0
        static Expression Create(ExpressionNodeInfo info, ExpressionSyntax expression, SimpleNameSyntax name)
        {
            if (IsDynamic(info.Context, expression))
            {
                var expr = new MemberAccess(info.SetKind(ExprKind.DYNAMIC_MEMBER_ACCESS), expression, null);
                info.Context.TrapWriter.Writer.dynamic_member_name(expr, name.Identifier.Text);
                return(expr);
            }

            var target = info.SymbolInfo;

            if (target.CandidateReason == CandidateReason.OverloadResolutionFailure)
            {
                // Roslyn workaround. Even if we can't resolve a method, we know it's a method.
                return(Create(info.Context, expression, info.Parent, info.Child));
            }

            var symbol = target.Symbol ?? info.Context.GetSymbolInfo(name).Symbol;

            if (symbol == null && target.CandidateSymbols.Length >= 1)
            {
                // Pick the first symbol. This could occur for something like `nameof(Foo.Bar)`
                // where `Bar` is a method group. Technically, we don't know which symbol is accessed.
                symbol = target.CandidateSymbols[0];
            }

            if (symbol == null)
            {
                info.Context.ModelError(info.Node, "Failed to determine symbol for member access");
                // Default to property access - this can still give useful results but
                // the target of the expression should be checked in QL.
                return(new MemberAccess(info.SetKind(ExprKind.PROPERTY_ACCESS), expression, symbol));
            }

            ExprKind kind;

            switch (symbol.Kind)
            {
            case SymbolKind.Property:
                kind = ExprKind.PROPERTY_ACCESS;
                break;

            case SymbolKind.Method:
                kind = ExprKind.METHOD_ACCESS;
                break;

            case SymbolKind.Field:
                kind = ExprKind.FIELD_ACCESS;
                break;

            case SymbolKind.NamedType:
                return(TypeAccess.Create(info));

            case SymbolKind.Event:
                kind = ExprKind.EVENT_ACCESS;
                break;

            case SymbolKind.Namespace:
                kind = ExprKind.NAMESPACE_ACCESS;
                break;

            default:
                info.Context.ModelError(info.Node, "Unhandled symbol for member access");
                kind = ExprKind.UNKNOWN;
                break;
            }
            return(new MemberAccess(info.SetKind(kind), expression, symbol));
        }