Esempio n. 1
0
        /// <summary>
        /// Returns true if this node evaluates to an empty string,
        /// otherwise false.
        /// It may be cheaper to determine whether an expression will evaluate
        /// to empty than to fully evaluate it.
        /// Implementations should cache the result so that calls after the first are free.
        /// </summary>
        internal override bool EvaluatesToEmpty(IConditionEvaluationState state)
        {
            if (_cachedExpandedValue == null)
            {
                if (_expandable)
                {
                    string expandBreakEarly = state.ExpandIntoStringBreakEarly(_value);

                    if (expandBreakEarly == null)
                    {
                        // It broke early: we can't store the value, we just
                        // know it's non empty
                        return(false);
                    }

                    // It didn't break early, the result is accurate,
                    // so store it so the work isn't done again.
                    _cachedExpandedValue = expandBreakEarly;
                }
                else
                {
                    _cachedExpandedValue = _value;
                }
            }

            return(_cachedExpandedValue.Length == 0);
        }
Esempio n. 2
0
        /// <summary>
        /// Evaluates as boolean and evaluates children as boolean, numeric, or string.
        /// Order in which comparisons are attempted is numeric, boolean, then string.
        /// Updates conditioned properties table.
        /// </summary>
        internal override bool BoolEvaluate(IConditionEvaluationState state)
        {
            // It's sometimes possible to bail out of expansion early if we just need to know whether
            // the result is empty string.
            // If at least one of the left or the right hand side will evaluate to empty,
            // and we know which do, then we already have enough information to evaluate this expression.
            // That means we don't have to fully expand a condition like " '@(X)' == '' "
            // which is a performance advantage if @(X) is a huge item list.
            if (this.LeftChild.EvaluatesToEmpty(state) || this.RightChild.EvaluatesToEmpty(state))
            {
                UpdateConditionedProperties(state);

                return(Compare(this.LeftChild.EvaluatesToEmpty(state), this.RightChild.EvaluatesToEmpty(state)));
            }

            if (this.LeftChild.CanNumericEvaluate(state) && this.RightChild.CanNumericEvaluate(state))
            {
                return(Compare(this.LeftChild.NumericEvaluate(state), this.RightChild.NumericEvaluate(state)));
            }
            else if (this.LeftChild.CanBoolEvaluate(state) && this.RightChild.CanBoolEvaluate(state))
            {
                return(Compare(this.LeftChild.BoolEvaluate(state), this.RightChild.BoolEvaluate(state)));
            }
            else // string comparison
            {
                string leftExpandedValue  = this.LeftChild.GetExpandedValue(state);
                string rightExpandedValue = this.RightChild.GetExpandedValue(state);

                UpdateConditionedProperties(state);

                return(Compare(leftExpandedValue, rightExpandedValue));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Evaluate as boolean
        /// </summary>
        internal override bool BoolEvaluate(IConditionEvaluationState state)
        {
            bool isLeftNum      = this.LeftChild.CanNumericEvaluate(state);
            bool isLeftVersion  = this.LeftChild.CanVersionEvaluate(state);
            bool isRightNum     = this.RightChild.CanNumericEvaluate(state);
            bool isRightVersion = this.RightChild.CanVersionEvaluate(state);
            bool isNumeric      = isLeftNum && isRightNum;
            bool isVersion      = isLeftVersion && isRightVersion;

            // If the values identify as numeric, make that comparison instead of the Version comparison since numeric has a stricter definition
            if (isNumeric)
            {
                return(Compare(this.LeftChild.NumericEvaluate(state), this.RightChild.NumericEvaluate(state)));
            }
            else if (isVersion)
            {
                return(Compare(this.LeftChild.VersionEvaluate(state), this.RightChild.VersionEvaluate(state)));
            }

            // If the numbers are of a mixed type, call that specific Compare method
            if (isLeftNum && isRightVersion)
            {
                return(Compare(this.LeftChild.NumericEvaluate(state), this.RightChild.VersionEvaluate(state)));
            }
            else if (isLeftVersion && isRightNum)
            {
                return(Compare(this.LeftChild.VersionEvaluate(state), this.RightChild.NumericEvaluate(state)));
            }

            // Throw error here as this code should be unreachable
            ErrorUtilities.ThrowInternalErrorUnreachable();
            return(false);
        }
Esempio n. 4
0
        /// <summary>
        /// Updates the conditioned properties table if it hasn't already been done.
        /// </summary>
        private void UpdateConditionedProperties(IConditionEvaluationState state)
        {
            if (!this._conditionedPropertiesUpdated && state.ConditionedPropertiesInProject != null)
            {
                string leftUnexpandedValue  = this.LeftChild.GetUnexpandedValue(state);
                string rightUnexpandedValue = this.RightChild.GetUnexpandedValue(state);

                if (leftUnexpandedValue != null)
                {
                    ConditionEvaluator.UpdateConditionedPropertiesTable
                        (state.ConditionedPropertiesInProject,
                        leftUnexpandedValue,
                        this.RightChild.GetExpandedValue(state));
                }

                if (rightUnexpandedValue != null)
                {
                    ConditionEvaluator.UpdateConditionedPropertiesTable
                        (state.ConditionedPropertiesInProject,
                        rightUnexpandedValue,
                        this.LeftChild.GetExpandedValue(state));
                }

                this._conditionedPropertiesUpdated = true;
            }
        }
        /// <summary>
        /// Whether it can be evaluated as a Version
        /// </summary>
        internal override bool CanVersionEvaluate(IConditionEvaluationState state)
        {
            // Check if the value can be formatted as a Version number
            // This is needed for nodes that identify as Numeric but can't be parsed as numbers (e.g. 8.1.1.0 vs 8.1)
            Version unused;

            return(Version.TryParse(_value, out unused));
        }
Esempio n. 6
0
 /// <summary>
 /// Evaluate as boolean
 /// </summary>
 internal override bool BoolEvaluate(IConditionEvaluationState state)
 {
     if (LeftChild.BoolEvaluate(state))
     {
         // Short circuit
         return(true);
     }
     else
     {
         return(RightChild.BoolEvaluate(state));
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Value after any item and property expressions are expanded
        /// </summary>
        /// <returns></returns>
        internal override string GetExpandedValue(IConditionEvaluationState state)
        {
            if (_cachedExpandedValue == null)
            {
                if (_expandable)
                {
                    _cachedExpandedValue = state.ExpandIntoString(_value);
                }
                else
                {
                    _cachedExpandedValue = _value;
                }
            }

            return(_cachedExpandedValue);
        }
        /// <summary>
        /// Evaluate node as boolean
        /// </summary>
        internal override bool BoolEvaluate(IConditionEvaluationState state)
        {
            if (String.Compare(_functionName, "exists", StringComparison.OrdinalIgnoreCase) == 0)
            {
                return(true);
            }

            if (String.Compare(_functionName, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // often used to append slash to path so return false to enable this codepath
                return(false);
            }

            // We haven't implemented any other "functions"

            return(false);
        }
 /// <summary>
 /// Value before any item and property expressions are expanded
 /// </summary>
 /// <returns></returns>
 internal override string GetUnexpandedValue(IConditionEvaluationState state)
 {
     return(null);
 }
Esempio n. 10
0
 internal abstract Version VersionEvaluate(IConditionEvaluationState state);
 /// <summary>
 /// Whether it can be evaluated as a boolean: never allowed for numerics
 /// </summary>
 internal override bool CanBoolEvaluate(IConditionEvaluationState state)
 {
     // Numeric expressions are never allowed to be treated as booleans.
     return(false);
 }
Esempio n. 12
0
 /// <summary>
 /// Value before any item and property expressions are expanded
 /// </summary>
 /// <returns></returns>
 internal abstract string GetUnexpandedValue(IConditionEvaluationState state);
Esempio n. 13
0
        internal override bool CanVersionEvaluate(IConditionEvaluationState state)
        {
            Version unused;

            return(Version.TryParse(GetExpandedValue(state), out unused));
        }
Esempio n. 14
0
 internal override bool CanNumericEvaluate(IConditionEvaluationState state)
 {
     return(ConversionUtilities.ValidDecimalOrHexNumber(GetExpandedValue(state)));
 }
Esempio n. 15
0
 internal override bool CanBoolEvaluate(IConditionEvaluationState state)
 {
     return(ConversionUtilities.CanConvertStringToBool(GetExpandedValue(state)));
 }
Esempio n. 16
0
 internal override Version VersionEvaluate(IConditionEvaluationState state)
 {
     return(Version.Parse(GetExpandedValue(state)));
 }
Esempio n. 17
0
 /// <summary>
 /// The main evaluate entry point for expression trees
 /// </summary>
 /// <param name="state"></param>
 /// <returns></returns>
 internal bool Evaluate(IConditionEvaluationState state)
 {
     return(BoolEvaluate(state));
 }
Esempio n. 18
0
 internal override bool CanBoolEvaluate(IConditionEvaluationState state)
 {
     return(this.LeftChild.CanBoolEvaluate(state));
 }
Esempio n. 19
0
 /// <summary>
 /// Returns expanded value with '!' prepended. Useful for error messages.
 /// </summary>
 internal override string GetExpandedValue(IConditionEvaluationState state)
 {
     return("!" + this.LeftChild.GetExpandedValue(state));
 }
 /// <summary>
 /// Evaluate as numeric
 /// </summary>
 internal override double NumericEvaluate(IConditionEvaluationState state)
 {
     return(ConversionUtilities.ConvertDecimalOrHexToDouble(_value));
 }
 /// <summary>
 /// Numeric evaluation is never allowed for operators
 /// </summary>
 internal override double NumericEvaluate(IConditionEvaluationState state)
 {
     // Should be unreachable: all calls check CanNumericEvaluate() first
     ErrorUtilities.VerifyThrow(false, "Cannot numeric evaluate an operator");
     return(0.0D);
 }
Esempio n. 22
0
 /// <summary>
 /// Returns true if this node evaluates to an empty string,
 /// otherwise false.
 /// (It may be cheaper to determine whether an expression will evaluate
 /// to empty than to fully evaluate it.)
 /// Implementations should cache the result so that calls after the first are free.
 /// </summary>
 internal virtual bool EvaluatesToEmpty(IConditionEvaluationState state)
 {
     return(false);
 }
 /// <summary>
 /// Evaluate as boolean
 /// </summary>
 internal override bool BoolEvaluate(IConditionEvaluationState state)
 {
     // Should be unreachable: all calls check CanBoolEvaluate() first
     ErrorUtilities.VerifyThrow(false, "Can't evaluate a numeric expression as boolean.");
     return(false);
 }
 /// <summary>
 /// Version evaluation is never allowed for operators
 /// </summary>
 internal override Version VersionEvaluate(IConditionEvaluationState state)
 {
     ErrorUtilities.VerifyThrow(false, "Cannot version evaluate an operator");
     return(null);
 }
 /// <summary>
 /// Evaluate as a Version
 /// </summary>
 internal override Version VersionEvaluate(IConditionEvaluationState state)
 {
     return(Version.Parse(_value));
 }
 /// <summary>
 /// Whether boolean evaluation is allowed: always allowed for operators
 /// </summary>
 internal override bool CanBoolEvaluate(IConditionEvaluationState state)
 {
     return(true);
 }
 /// <summary>
 /// Whether it can be evaluated as numeric
 /// </summary>
 internal override bool CanNumericEvaluate(IConditionEvaluationState state)
 {
     // It is not always possible to numerically evaluate even a numerical expression -
     // for example, it may overflow a double. So check here.
     return(ConversionUtilities.ValidDecimalOrHexNumber(_value));
 }
 /// <summary>
 /// Whether the node can be evaluated as a version: by default,
 /// this is not allowed
 /// </summary>
 internal override bool CanVersionEvaluate(IConditionEvaluationState state)
 {
     return(false);
 }
 /// <summary>
 /// Get the expanded value
 /// </summary>
 internal override string GetExpandedValue(IConditionEvaluationState state)
 {
     return(_value);
 }
Esempio n. 30
0
 internal abstract double NumericEvaluate(IConditionEvaluationState state);