예제 #1
0
        /// <summary>
        /// Evaluate as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluationState state)
        {
            ProjectErrorUtilities.VerifyThrowInvalidProject
                    (LeftChild.CanBoolEvaluate(state),
                     state.conditionAttribute,
                     "ExpressionDoesNotEvaluateToBoolean",
                     LeftChild.GetUnexpandedValue(state),
                     LeftChild.GetExpandedValue(state),
                     state.parsedCondition);

            if (LeftChild.BoolEvaluate(state))
            {
                // Short circuit
                return true;
            }
            else
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject
                    (RightChild.CanBoolEvaluate(state),
                     state.conditionAttribute,
                     "ExpressionDoesNotEvaluateToBoolean",
                     RightChild.GetUnexpandedValue(state),
                     RightChild.GetExpandedValue(state),
                     state.parsedCondition);

                return RightChild.BoolEvaluate(state);
            }
        }
예제 #2
0
        /// <summary>
        /// Value after any item and property expressions are expanded
        /// </summary>
        /// <returns></returns>
        internal override string GetExpandedValue(ConditionEvaluationState state)
        {
            if (cachedExpandedValue == null)
            {
                cachedExpandedValue = state.expanderToUse.ExpandAllIntoString(value, state.conditionAttribute);
            }

            return cachedExpandedValue;
        }
예제 #3
0
        /// <summary>
        /// The main evaluate entry point for expression trees
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        internal bool Evaluate(ConditionEvaluationState state)
        {
            ProjectErrorUtilities.VerifyThrowInvalidProject(
                CanBoolEvaluate(state),
                state.conditionAttribute,
                "ConditionNotBooleanDetail",
                state.parsedCondition,
                GetExpandedValue(state));

            return BoolEvaluate(state);
        }
        /// <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(ConditionEvaluationState state)
        {
            ProjectErrorUtilities.VerifyThrowInvalidProject
                (LeftChild != null && RightChild != null,
                 state.conditionAttribute,
                 "IllFormedCondition",
                 state.parsedCondition);

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

                ProjectErrorUtilities.VerifyThrowInvalidProject
                    (leftExpandedValue != null && rightExpandedValue != null, 
                     state.conditionAttribute, 
                     "IllFormedCondition", 
                     state.parsedCondition);

                if (!conditionedPropertiesUpdated)
                {
                    string leftUnexpandedValue = LeftChild.GetUnexpandedValue(state);
                    string rightUnexpandedValue = RightChild.GetUnexpandedValue(state);

                    if (leftUnexpandedValue != null)
                    {
                        Utilities.UpdateConditionedPropertiesTable
                            (state.conditionedPropertiesInProject, 
                             leftUnexpandedValue, 
                             rightExpandedValue);
                    }

                    if (rightUnexpandedValue != null)
                    {
                        Utilities.UpdateConditionedPropertiesTable
                            (state.conditionedPropertiesInProject, 
                             rightUnexpandedValue, 
                             leftExpandedValue);
                    }

                    conditionedPropertiesUpdated = true;
                }

                return Compare(leftExpandedValue, rightExpandedValue);
            }
        }
        /// <summary>
        /// Evaluate as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluationState state)
        {
            ProjectErrorUtilities.VerifyThrowInvalidProject
                (LeftChild.CanNumericEvaluate(state) && RightChild.CanNumericEvaluate(state),
                 state.conditionAttribute, 
                "ComparisonOnNonNumericExpression",
                 state.parsedCondition,
                 /* helpfully display unexpanded token and expanded result in error message */
                 (LeftChild.CanNumericEvaluate(state) ? RightChild.GetUnexpandedValue(state) : LeftChild.GetUnexpandedValue(state)),
                 (LeftChild.CanNumericEvaluate(state) ? RightChild.GetExpandedValue(state) : LeftChild.GetExpandedValue(state)));

            return Compare(LeftChild.NumericEvaluate(state), RightChild.NumericEvaluate(state));
        }
예제 #6
0
        public void SimpleEvaluationTests()
        {
            Parser p = new Parser();
            Expander expander = new Expander(new BuildPropertyGroup());
            Hashtable conditionedProperties = null;
            ConditionEvaluationState state = new ConditionEvaluationState(DummyAttribute, expander, conditionedProperties, string.Empty);

            AssertParseEvaluate(p, "true", state, true);
            AssertParseEvaluate(p, "on", state, true);
            AssertParseEvaluate(p, "yes", state, true);
            AssertParseEvaluate(p, "false", state, false);
            AssertParseEvaluate(p, "off", state, false);
            AssertParseEvaluate(p, "no", state, false);
        }
예제 #7
0
 /// <summary>
 /// Whether it can be evaluated as a boolean: never allowed for numerics
 /// </summary>
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     // Numeric expressions are never allowed to be treated as booleans.
     return false;
 }
예제 #8
0
 internal override string GetExpandedValue(ConditionEvaluationState state)
 {
     return value;
 }
예제 #9
0
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     return(ConversionUtilities.CanConvertStringToBool(GetExpandedValue(state)));
 }
예제 #10
0
 /// <summary>
 /// Value before any item and property expressions are expanded
 /// </summary>
 /// <returns></returns>
 internal override string GetUnexpandedValue(ConditionEvaluationState state)
 {
     return(value);
 }
예제 #11
0
 /// <summary>
 /// Value before any item and property expressions are expanded
 /// </summary>
 /// <returns></returns>
 internal override string GetUnexpandedValue(ConditionEvaluationState state)
 {
     return null;
 }
        /// <summary>
        /// Evaluate node as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluationState state)
        {
            if (String.Equals(functionName, "exists", StringComparison.OrdinalIgnoreCase))
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("exists", (GenericExpressionNode)arguments[0], state);

                if (Project.PerThreadProjectDirectory != null && !String.IsNullOrEmpty(expandedValue))
                {
                    try
                    {
                        expandedValue = Path.GetFullPath(Path.Combine(Project.PerThreadProjectDirectory, expandedValue));
                    }
                    catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception.
                    {
                        if (ExceptionHandling.NotExpectedException(e))
                        {
                            throw;
                        }

                        // Ignore invalid characters or path related exceptions

                        // We will ignore the PathTooLong exception caused by GetFullPath becasue in single proc this code
                        // is not executed and the condition is just evaluated to false as File.Exists and Directory.Exists does not throw in this situation.
                        // To be consistant with that we will return a false in this case also.
                        // DevDiv Bugs: 46035

                        return(false);
                    }
                }

                // Both Exists functions return false if the value is null or empty
                return(File.Exists(expandedValue) || Directory.Exists(expandedValue));
            }
            else if (String.Equals(functionName, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase))
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("HasTrailingSlash", (GenericExpressionNode)arguments[0], state);

                // Is the last character a backslash?
                if (expandedValue.Length != 0)
                {
                    char lastCharacter = expandedValue[expandedValue.Length - 1];
                    // Either back or forward slashes satisfy the function: this is useful for URL's
                    return(lastCharacter == Path.DirectorySeparatorChar || lastCharacter == Path.AltDirectorySeparatorChar);
                }
                else
                {
                    return(false);
                }
            }
            // We haven't implemented any other "functions"
            else
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject(
                    false,
                    state.conditionAttribute,
                    "UndefinedFunctionCall",
                    state.parsedCondition,
                    this.functionName);

                return(false);
            }
        }
예제 #13
0
 /// <summary>
 /// Returns expanded value with '!' prepended. Useful for error messages.
 /// </summary>
 internal override string GetExpandedValue(ConditionEvaluationState state)
 {
     return "!" + LeftChild.GetExpandedValue(state);
 }
예제 #14
0
        private void AssertParseEvaluateThrow(Parser p, string expression, ConditionEvaluationState state)
        {
            bool fExceptionCaught;

            try
            {
                fExceptionCaught = false;
                GenericExpressionNode tree = p.Parse(expression, DummyAttribute, ParserOptions.AllowAll);
                state.parsedCondition = expression;
                tree.Evaluate(state);
            }
            catch (InvalidProjectFileException e)
            {
                Console.WriteLine(e.BaseMessage);
                fExceptionCaught = true;
            }

            Assertion.Assert(fExceptionCaught);
        }
예제 #15
0
 private bool EvaluateCondition(string conditionExpression, Expander expander)
 {
     Parser p = new Parser();
     ConditionEvaluationState state = new ConditionEvaluationState(DummyAttribute, expander, null, conditionExpression);
     GenericExpressionNode node = p.Parse(conditionExpression, DummyAttribute, ParserOptions.AllowAll);
     bool result = node.Evaluate(state);
     return result;
 }
예제 #16
0
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     return LeftChild.CanBoolEvaluate(state);
 }
예제 #17
0
 /// <summary>
 /// Returns expanded value with '!' prepended. Useful for error messages.
 /// </summary>
 internal override string GetExpandedValue(ConditionEvaluationState state)
 {
     return("!" + LeftChild.GetExpandedValue(state));
 }
예제 #18
0
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     return(LeftChild.CanBoolEvaluate(state));
 }
예제 #19
0
        /// <summary>
        /// Evaluate node as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluationState state)
        {
            if (String.Compare(functionName, "exists", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("exists", (GenericExpressionNode)arguments[0], state);

                if (Project.PerThreadProjectDirectory != null && !String.IsNullOrEmpty(expandedValue))
                {
                    try 
                    {
                        expandedValue = Path.GetFullPath(Path.Combine(Project.PerThreadProjectDirectory, expandedValue));
                    }
                    catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception.
                    {
                        if (ExceptionHandling.NotExpectedException(e))
                            throw;

                        // Ignore invalid characters or path related exceptions

                        // We will ignore the PathTooLong exception caused by GetFullPath becasue in single proc this code 
                        // is not executed and the condition is just evaluated to false as File.Exists and Directory.Exists does not throw in this situation. 
                        // To be consistant with that we will return a false in this case also.
                        // DevDiv Bugs: 46035

                        return false;
                    }

                }

                // Both Exists functions return false if the value is null or empty
                return File.Exists(expandedValue) || Directory.Exists(expandedValue);
            }
            else if (String.Compare(functionName, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("HasTrailingSlash", (GenericExpressionNode)arguments[0], state);

                // Is the last character a backslash?
                if (expandedValue.Length != 0)
                {
                    char lastCharacter = expandedValue[expandedValue.Length - 1];
                    // Either back or forward slashes satisfy the function: this is useful for URL's
                    return (lastCharacter == Path.DirectorySeparatorChar || lastCharacter == Path.AltDirectorySeparatorChar);
                }
                else
                {
                    return false;
                }
            }
            // We haven't implemented any other "functions"
            else
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject(
                    false,
                    state.conditionAttribute, 
                    "UndefinedFunctionCall",
                    state.parsedCondition, 
                    this.functionName);

                return false;
            }
        }
예제 #20
0
 internal abstract bool CanNumericEvaluate(ConditionEvaluationState state);
예제 #21
0
 internal abstract bool CanNumericEvaluate(ConditionEvaluationState state);
예제 #22
0
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     return ConversionUtilities.CanConvertStringToBool(GetExpandedValue(state));
 }
예제 #23
0
 internal abstract bool BoolEvaluate(ConditionEvaluationState state);
예제 #24
0
 /// <summary>
 /// Whether boolean evaluation is allowed: always allowed for operators
 /// </summary>
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     return true;
 }
예제 #25
0
 internal abstract double NumericEvaluate(ConditionEvaluationState state);
예제 #26
0
 /// <summary>
 /// Check that the number of function arguments is correct.
 /// </summary>
 /// <param name="expected"></param>
 private void VerifyArgumentCount(int expected, ConditionEvaluationState state)
 {
     ProjectErrorUtilities.VerifyThrowInvalidProject
         (arguments.Count == expected,
          state.conditionAttribute,
          "IncorrectNumberOfFunctionArguments",
          state.parsedCondition,
          arguments.Count,
          expected);
 }
예제 #27
0
 /// <summary>
 /// Value before any item and property expressions are expanded
 /// </summary>
 /// <returns></returns>
 internal abstract string GetUnexpandedValue(ConditionEvaluationState state);
예제 #28
0
 /// <summary>
 /// Evaluate as numeric
 /// </summary>
 internal override double NumericEvaluate(ConditionEvaluationState state)
 {
     return(ConversionUtilities.ConvertDecimalOrHexToDouble(GetExpandedValue(state)));
 }
예제 #29
0
        public void NegativeTests()
        {
            Parser p = new Parser();
            Expander expander = new Expander(new BuildPropertyGroup());
            Hashtable conditionedProperties = null;
            ConditionEvaluationState state = new ConditionEvaluationState(DummyAttribute, expander, conditionedProperties, string.Empty);

            AssertParseEvaluateThrow(p, "foobar", state);
            AssertParseEvaluateThrow(p, "0", state);
            AssertParseEvaluateThrow(p, "$(platform) == xx > 1==2", state);
            AssertParseEvaluateThrow(p, "!0", state);
            AssertParseEvaluateThrow(p, ">", state);
            AssertParseEvaluateThrow(p, "true!=false==", state);
            AssertParseEvaluateThrow(p, "()", state);
            AssertParseEvaluateThrow(p, "!1", state);
            AssertParseEvaluateThrow(p, "true!=false==true", state);
            AssertParseEvaluateThrow(p, "'a'>'a'", state);
            AssertParseEvaluateThrow(p, "=='x'", state);
            AssertParseEvaluateThrow(p, "==", state);
            AssertParseEvaluateThrow(p, "1==(2", state);
            AssertParseEvaluateThrow(p, "'a'==('a'=='a')", state);
            AssertParseEvaluateThrow(p, "true == on and ''", state);
            AssertParseEvaluateThrow(p, "'' or 'true'", state);
        }
예제 #30
0
 internal override bool CanNumericEvaluate(ConditionEvaluationState state)
 {
     return(ConversionUtilities.ValidDecimalOrHexNumber(GetExpandedValue(state)));
 }
예제 #31
0
 /// <summary>
 /// Numeric evaluation is never allowed for operators
 /// </summary>
 internal override double NumericEvaluate(ConditionEvaluationState state)
 {
     // Should be unreachable: all calls check CanNumericEvaluate() first
     ErrorUtilities.VerifyThrow(false, "Cannot numeric evaluate an operator");
     return(0.0D);
 }
예제 #32
0
 /// <summary>
 /// Evaluate as boolean
 /// </summary>
 internal override bool BoolEvaluate(ConditionEvaluationState state)
 {
     // Should be unreachable: all calls check CanBoolEvaluate() first
     ErrorUtilities.VerifyThrow(false, "Can't evaluate a numeric expression as boolean.");
     return false;
 }
예제 #33
0
 /// <summary>
 /// Whether boolean evaluation is allowed: always allowed for operators
 /// </summary>
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     return(true);
 }
예제 #34
0
 internal override bool CanNumericEvaluate(ConditionEvaluationState 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);
 }
예제 #35
0
 /// <summary>
 /// Whether the node can be evaluated as a numeric: by default,
 /// this is not allowed
 /// </summary>
 internal override bool CanNumericEvaluate(ConditionEvaluationState state)
 {
     return(false);
 }
예제 #36
0
 internal abstract bool CanBoolEvaluate(ConditionEvaluationState state);
예제 #37
0
 /// <summary>
 /// Value after any item and property expressions are expanded
 /// </summary>
 /// <returns></returns>
 internal override string GetExpandedValue(ConditionEvaluationState state)
 {
     return(null);
 }
예제 #38
0
 /// <summary>
 /// Evaluate as numeric
 /// </summary>
 internal override double NumericEvaluate(ConditionEvaluationState state)
 {
     return ConversionUtilities.ConvertDecimalOrHexToDouble(GetExpandedValue(state));
 }
예제 #39
0
        public void NotTests()
        {
            Console.WriteLine("NegationParseTest()");
            Parser p = new Parser();
            Hashtable conditionedProperties = null;

            BuildPropertyGroup propertyBag = new BuildPropertyGroup();
            propertyBag.SetProperty("foo", "4");
            propertyBag.SetProperty("bar", "32");

            Expander expander = new Expander(propertyBag);
            ConditionEvaluationState state = new ConditionEvaluationState(DummyAttribute, expander, conditionedProperties, string.Empty);

            AssertParseEvaluate(p, "!true", state, false);
            AssertParseEvaluate(p, "!(true)", state, false);
            AssertParseEvaluate(p, "!($(foo) <= 5)", state, false);
            AssertParseEvaluate(p, "!($(foo) <= 5 and $(bar) >= 15)", state, false);
        }
예제 #40
0
 internal override bool CanNumericEvaluate(ConditionEvaluationState state)
 {
     return ConversionUtilities.ValidDecimalOrHexNumber(GetExpandedValue(state));
 }
예제 #41
0
 /// <summary>
 /// Whether it can be evaluated as a boolean: never allowed for numerics
 /// </summary>
 internal override bool CanBoolEvaluate(ConditionEvaluationState state)
 {
     // Numeric expressions are never allowed to be treated as booleans.
     return(false);
 }
예제 #42
0
 /// <summary>
 /// Numeric evaluation is never allowed for operators
 /// </summary>
 internal override double NumericEvaluate(ConditionEvaluationState state)
 {
     // Should be unreachable: all calls check CanNumericEvaluate() first
     ErrorUtilities.VerifyThrow(false, "Cannot numeric evaluate an operator");
     return 0.0D;
 }
예제 #43
0
 internal override bool CanNumericEvaluate(ConditionEvaluationState 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));
 }
예제 #44
0
 /// <summary>
 /// Whether the node can be evaluated as a numeric: by default,
 /// this is not allowed
 /// </summary>
 internal override bool CanNumericEvaluate(ConditionEvaluationState state)
 {
     return false;
 }
        /// <summary>
        /// Expands properties and items in the argument, and verifies that the result is consistent
        /// with a scalar parameter type.
        /// </summary>
        /// <param name="function">Function name for errors</param>
        /// <param name="argumentNode">Argument to be expanded</param>
        /// <returns>Scalar result</returns>
        /// <owner>danmose</owner>
        private string ExpandArgumentForScalarParameter(string function, GenericExpressionNode argumentNode, ConditionEvaluationState state)
        {
            string argument = argumentNode.GetUnexpandedValue(state);

            List <TaskItem> items = state.expanderToUse.ExpandAllIntoTaskItems(argument, state.conditionAttribute);

            string expandedValue = String.Empty;

            if (items.Count == 0)
            {
                // Empty argument, that's fine.
            }
            else if (items.Count == 1)
            {
                expandedValue = items[0].ItemSpec;
            }
            else // too many items for the function
            {
                // We only allow a single item to be passed into a scalar parameter.
                ProjectErrorUtilities.VerifyThrowInvalidProject(false,
                                                                state.conditionAttribute,
                                                                "CannotPassMultipleItemsIntoScalarFunction", function, argument,
                                                                state.expanderToUse.ExpandAllIntoString(argument, state.conditionAttribute));
            }

            return(expandedValue);
        }
예제 #46
0
 /// <summary>
 /// Evaluate as boolean
 /// </summary>
 internal override bool BoolEvaluate(ConditionEvaluationState state)
 {
     // Should be unreachable: all calls check CanBoolEvaluate() first
     ErrorUtilities.VerifyThrow(false, "Can't evaluate a numeric expression as boolean.");
     return(false);
 }
예제 #47
0
        /// <summary>
        /// Expands properties and items in the argument, and verifies that the result is consistent
        /// with a scalar parameter type.
        /// </summary>
        /// <param name="function">Function name for errors</param>
        /// <param name="argumentNode">Argument to be expanded</param>
        /// <returns>Scalar result</returns>
        /// <owner>danmose</owner>
        private string ExpandArgumentForScalarParameter(string function, GenericExpressionNode argumentNode, ConditionEvaluationState state)
        {
            string argument = argumentNode.GetUnexpandedValue(state);

            List<TaskItem> items = state.expanderToUse.ExpandAllIntoTaskItems(argument, state.conditionAttribute); 

            string expandedValue = String.Empty;

            if (items.Count == 0)
            {
                // Empty argument, that's fine.
            }
            else if (items.Count == 1)
            {
                expandedValue = items[0].ItemSpec;
            }
            else // too many items for the function
            {
                // We only allow a single item to be passed into a scalar parameter.
                ProjectErrorUtilities.VerifyThrowInvalidProject(false,
                    state.conditionAttribute,
                    "CannotPassMultipleItemsIntoScalarFunction", function, argument,
                    state.expanderToUse.ExpandAllIntoString(argument, state.conditionAttribute));
            }

            return expandedValue;
        }