-
Notifications
You must be signed in to change notification settings - Fork 352
/
Copy pathBinaryOperatorBinder.cs
96 lines (84 loc) · 4.55 KB
/
BinaryOperatorBinder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//---------------------------------------------------------------------
// <copyright file="BinaryOperatorBinder.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
namespace Microsoft.OData.UriParser
{
using System;
using Microsoft.OData.Edm;
using Microsoft.OData.Core;
/// <summary>
/// Class that knows how to bind binary operators.
/// </summary>
internal sealed class BinaryOperatorBinder
{
/// <summary>
/// Method to use for binding the parent node, if needed.
/// </summary>
private readonly Func<QueryToken, QueryNode> bindMethod;
/// <summary>
/// Resolver for parsing
/// </summary>
private readonly ODataUriResolver resolver;
/// <summary>
/// Constructs a BinaryOperatorBinder with the given method to be used binding the parent token if needed.
/// </summary>
/// <param name="bindMethod">Method to use for binding the parent token, if needed.</param>
/// <param name="resolver">Resolver for parsing.</param>
internal BinaryOperatorBinder(Func<QueryToken, QueryNode> bindMethod, ODataUriResolver resolver)
{
this.bindMethod = bindMethod;
this.resolver = resolver;
}
/// <summary>
/// Binds a binary operator token.
/// </summary>
/// <param name="binaryOperatorToken">The binary operator token to bind.</param>
/// <returns>The bound binary operator token.</returns>
internal QueryNode BindBinaryOperator(BinaryOperatorToken binaryOperatorToken)
{
ExceptionUtils.CheckArgumentNotNull(binaryOperatorToken, "binaryOperatorToken");
SingleValueNode left = this.GetOperandFromToken(binaryOperatorToken.OperatorKind, binaryOperatorToken.Left);
SingleValueNode right = this.GetOperandFromToken(binaryOperatorToken.OperatorKind, binaryOperatorToken.Right);
IEdmTypeReference typeReference;
this.resolver.PromoteBinaryOperandTypes(binaryOperatorToken.OperatorKind, ref left, ref right, out typeReference);
return new BinaryOperatorNode(binaryOperatorToken.OperatorKind, left, right, typeReference);
}
/// <summary>
/// Promote the left and right operand types
/// </summary>
/// <param name="binaryOperatorKind">the operator kind</param>
/// <param name="left">the left operand</param>
/// <param name="right">the right operand</param>
/// <param name="facetsPromotionRules">Promotion rules for type facets.</param>
internal static void PromoteOperandTypes(BinaryOperatorKind binaryOperatorKind, ref SingleValueNode left, ref SingleValueNode right, TypeFacetsPromotionRules facetsPromotionRules)
{
IEdmTypeReference leftType;
IEdmTypeReference rightType;
if (!TypePromotionUtils.PromoteOperandTypes(binaryOperatorKind, left, right, out leftType, out rightType, facetsPromotionRules))
{
string leftTypeName = left.TypeReference == null ? "<null>" : left.TypeReference.FullName();
string rightTypeName = right.TypeReference == null ? "<null>" : right.TypeReference.FullName();
throw new ODataException(Error.Format(SRResources.MetadataBinder_IncompatibleOperandsError, leftTypeName, rightTypeName, binaryOperatorKind));
}
left = MetadataBindingUtils.ConvertToTypeIfNeeded(left, leftType);
right = MetadataBindingUtils.ConvertToTypeIfNeeded(right, rightType);
}
/// <summary>
/// Retrieve SingleValueNode bound with given query token.
/// </summary>
/// <param name="operatorKind">the query token kind</param>
/// <param name="queryToken">the query token</param>
/// <returns>the corresponding SingleValueNode</returns>
private SingleValueNode GetOperandFromToken(BinaryOperatorKind operatorKind, QueryToken queryToken)
{
SingleValueNode operand = this.bindMethod(queryToken) as SingleValueNode;
if (operand == null)
{
throw new ODataException(Error.Format(SRResources.MetadataBinder_BinaryOperatorOperandNotSingleValue, operatorKind.ToString()));
}
return operand;
}
}
}