File: Evaluation\Conditionals\NumericComparisonExpressionNode.cs
Web Access
Project: ..\..\..\src\Build\Microsoft.Build.csproj (Microsoft.Build)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Shared;
 
#nullable disable
 
namespace Microsoft.Build.Evaluation
{
    /// <summary>
    /// Evaluates a numeric comparison, such as less-than, or greater-or-equal-than
    /// Does not update conditioned properties table.
    /// </summary>
    internal abstract class NumericComparisonExpressionNode : OperatorExpressionNode
    {
        /// <summary>
        /// Compare numbers
        /// </summary>
        protected abstract bool Compare(double left, double right);
 
        /// <summary>
        /// Compare Versions. This is only intended to compare version formats like "A.B.C.D" which can otherwise not be compared numerically
        /// </summary>
        protected abstract bool Compare(Version left, Version right);
 
        /// <summary>
        /// Compare mixed numbers and Versions
        /// </summary>
        protected abstract bool Compare(Version left, double right);
 
        /// <summary>
        /// Compare mixed numbers and Versions
        /// </summary>
        protected abstract bool Compare(double left, Version right);
 
        /// <summary>
        /// Evaluate as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state)
        {
            bool isLeftNum = LeftChild.TryNumericEvaluate(state, out double leftNum);
            bool isLeftVersion = LeftChild.TryVersionEvaluate(state, out Version leftVersion);
            bool isRightNum = RightChild.TryNumericEvaluate(state, out double rightNum);
            bool isRightVersion = RightChild.TryVersionEvaluate(state, out Version rightVersion);
 
            if ((!isLeftNum && !isLeftVersion) || (!isRightNum && !isRightVersion))
            {
                ProjectErrorUtilities.ThrowInvalidProject(
                    state.ElementLocation,
                    "ComparisonOnNonNumericExpression",
                    state.Condition,
                    /* helpfully display unexpanded token and expanded result in error message */
                    isLeftNum ? RightChild.GetUnexpandedValue(state) : LeftChild.GetUnexpandedValue(state),
                    isLeftNum ? RightChild.GetExpandedValue(state) : LeftChild.GetExpandedValue(state));
            }
 
            return (isLeftNum, isLeftVersion, isRightNum, isRightVersion) switch
            {
                (true, _, true, _) => Compare(leftNum, rightNum),
                (_, true, _, true) => Compare(leftVersion, rightVersion),
                (true, _, _, true) => Compare(leftNum, rightVersion),
                (_, true, true, _) => Compare(leftVersion, rightNum),
 
                _ => false
            };
        }
    }
}