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)); } } }
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)); }